简体   繁体   中英

How can I change data value from one component to another component in Vue Js?

I am new in Vue Js. So, I am facing a problem to changes data value from another component.

I have a component A:

<template>
   <div id="app">
      <p v-on:click="test ()">Something</p>
   </div>
</template>

import B from '../components/B.vue';
export default {
    components: {
        B
    },
    methods: {
        test: function() {
            B.data().myData = 124
            B.data().isActive = true
            console.log(B.data().myData);
            console.log(B.data().isActive);
        }
    }
}

Component B:

export default {
    data() {
        return {
            myData: 123,
            isActive: false

        }
    }

}

It still component B data. But it cannot be affected component B data. I want to data changes of component B from component A. How can I do that?

Please explain me in details. I have seen vue js props attribute but I don't understand.

You're looking for Vuex .

It's the centralized store for all the data in your applications.

Take a look at their documentation, it should be pretty straightforward.

You can pass down props to the component B. These props can be updated by the parent component. You can think of B as a stupid component that just renders what the parent tells it to rendern. Example:

// Component A
<template>
   <div id="app">
      <p v-on:click="test ()">Something</p>
      <b data="myData" isActive="myIsActive"></b>
   </div>
</template>

<script>
import B from '../components/B.vue';
export default {
  components: {
    B
  },
  data() {
    return {
      myData: 0,
      myIsActive: false,
    };
  },
  methods: {
    test: function() {
      this.myData = 123
      this.myIsActive = true
    }
  }
}
</script>

// Component B
<template>
  <div>{{ data }}{{ isActive }}</div>
</template>

<script>
export default {
  props: {
    data: Number,
    isActive: Boolean
};
</script>

There are few ways...

  1. if your components have a parent child relationship you can pass data values from parent into child.

  2. If your want to communicate back to parent component when child component has changed something, you can use vuejs event emitter(custom event) to emit a event when data value change and that event can be listened in another component and do what you want.

  3. If your components doesn't have a relationship, then you have to use use something else than above things. You can use two things.one is event bus, other one is state management library.for vue there is a official state management library called VueX.it is very easy to use.if you want to use something else than vuex, you can use it such as redux, mobx etc.

This documentation has everything what you want to know. I don't want to put any code, because of doc is very clear.

VueX is the most preferable way to do this! Very easy to use..

https://v2.vuejs.org/v2/guide/components.html

 //component A Vue.component('my-button', { props: ['title'], template: `<button v-on:click="$emit('add-value')">{{title}}</button>` }); Vue.component('my-viewer', { props: ['counter'], template: `<button>{{counter}}</button>` }); new Vue({ el: '#app', data: { counter: 0, }, methods: { doSomething: function() { this.counter++; } } }) Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' }); //parent new Vue({ el: '#blog-post-demo', data: { posts: [{ id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ] } }); Vue.component('blog-post2', { props: ['post'], template: ` <div class="blog-post"> <h3>{{ post.title }}</h3> <button v-on:click="$emit('enlarge-text')"> Enlarge text </button> <div v-html="post.content"></div> </div>` }) new Vue({ el: '#blog-posts-events-demo', data: { posts: [{ id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ], postFontSize: 1 }, methods: { onEnlargeText: function() { this.postFontSize++; } } })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <p>Two components adding & viewing value</p> <div id="app"> <my-button :title="'Add Value'" v-on:add-value="doSomething"></my-button> <my-viewer :counter="counter"></my-viewer> </div> <br> <br> <p>Passing Data to Child Components with Props (Parent to Child)</p> <div id="blog-post-demo"> <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title"></blog-post> </div> <p>Listening to Child Components Events (Child to Parent)</p> <div id="blog-posts-events-demo"> <div :style="{ fontSize: postFontSize + 'em' }"> <blog-post2 v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="onEnlargeText"></blog-post2> </div> </div>

First, you need a parent so two component can communicate. when my-button component is clicked triggers an event add-value that calls doSomething() function, then updates the value & show it to my-viewer component.

HTML

     <!--PARENT-->
     <div id="app"> 
          <!--CHILD COMPONENTS-->
          <my-button :title="'Add Value'" v-on:add-value="doSomething"></my-button>
          <my-viewer :counter="counter"></my-viewer>
     </div>

VUE.JS

     //component A
     Vue.component('my-button',{
         props:['title'],
         template:`<button v-on:click="$emit('add-value')">{{title}}</button>`
     });

     //Component B
     Vue.component('my-viewer',{
        props:['counter'],
        template:`<button>{{counter}}</button>`
     });

     //Parent
     new Vue({
         el: '#app',
         data:{
            counter:0,
         },
         methods:{
             doSomething:function(){
               this.counter++;
             }
        }
     })

This is base on Vue Components Guide

Passing Data to Child Components with Props (Parent to Child)

VUE.JS

         //component (child)
         //Vue component must come first, else it won't work
         Vue.component('blog-post', {
             /*Props are custom attributes you can register on a component. When a 
               value is passed to a prop attribute, it becomes a property on that 
               component instance*/
             props: ['title'],
             template: '<h3>{{ title }}</h3>'
         });

         //parent
         new Vue({
            el: '#blog-post-demo',
            data: {
              posts: [
                 { id: 1, title: 'My journey with Vue' },
                 { id: 2, title: 'Blogging with Vue' },
                 { id: 3, title: 'Why Vue is so fun' }
              ]
            }
         });

HTML:

v-for will loop on posts and pass data to blog-post component

         <div id="blog-post-demo">
             <blog-post  v-for="post in posts"
                         v-bind:key="post.id"
                         v-bind:title="post.title"></blog-post>
         </div>

Listening to Child Components Events (Child to Parent)

HTML

You must first register the event by v-on:enlarge-text="onEnlargeText" to use $emit and make sure that it's always set to lower case or it won't work properly. example enlargeText and Enlargetext will always be converted to enlargetext , thus use enlarge-text instead, because its easy to read & valid, for a brief explanation about $emit you can read it here

         <div id="blog-posts-events-demo">
            <div :style="{ fontSize: postFontSize + 'em' }">
                 <blog-post
                          v-for="post in posts"
                          v-bind:key="post.id"
                          v-bind:post="post"
                          v-on:enlarge-text="onEnlargeText"></blog-post>
            </div>
         </div>
     

VUE.JS

When user clicks the button the v-on:click="$emit('enlarge-text')" will trigger then calling the function onEnlargeText() in the parent

         //component (child)
         Vue.component('blog-post', {
             props: ['post'],
             template: `
              <div class="blog-post">
                 <h3>{{ post.title }}</h3>
                 <button v-on:click="$emit('enlarge-text')">
                     Enlarge text
                 </button>
                 <div v-html="post.content"></div>
             </div>`
         })

         //parent
         new Vue({
            el: '#blog-posts-events-demo',
            data: {
               posts: [
                    { id: 1, title: 'My journey with Vue' },
                    { id: 2, title: 'Blogging with Vue' },
                    { id: 3, title: 'Why Vue is so fun' }
               ],
            postFontSize: 1
         },
         methods:{
            onEnlargeText:function(){
               this.postFontSize++;
            }
          }
        })

Actually props suck sometimes you got some old external library in jquyer and need just damn pass value. in 99% of time use props that do job but.

A) spend tons of hours debuging changing tones of code to pass variables B) one line solution

Create main variable in data letmeknow as object {}

this.$root.letmeknow

then somewhere in code from component

this.$root.letmeknow = this;

and then boom i got component console.log( this.$root.letmeknow ) and see now can change some values

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM