如何在Vue Js中从一个组件更改数据值到另一个组件?

15

我是 Vue Js 的新手。因此,我遇到了一个问题,即如何从另一个组件更改数据值。

我有一个 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);
        }
    }
}

组件 B:

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

        }
    }

}

仍然存在组件B的数据。 但是不能影响组件B的数据。 我想从组件A更改组件B的数据。 我该怎么做?

请详细解释给我。 我看过Vue.js的props属性,但不理解。


你能更新一下哪个是A组件,哪个是B组件吗? - Muthu Kumaran
我更新了我的代码。请查看并回答我。 - Sukanta Bala
5个回答

9

你正在寻找Vuex

它是应用程序中所有数据的集中式存储。

看一下他们的文档,应该很容易理解。


1
我认为这是对所提出问题的正确答案。另一种解决方案将数据和数据驱动程序移入组件A,并假设组件B仅是一个显示组件。我认为问题更类似于将组件A作为布局,其中可能包括一些操作按钮,而组件B则是存储所有数据并进行转换的地方。Vuex可以解决这种情况。 - nelsonenzo

4
您可以将props传递给组件B。这些props可以由父组件更新。您可以将B视为一个愚蠢的组件,它只会呈现其父组件要求呈现的内容。例如:
// 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>

2
有几种方法...
  1. 如果你的组件有父子关系,你可以把数据值从父组件传递到子组件。

  2. 如果你想在子组件更改了某些内容后回到父组件进行通信,你可以使用Vue.js事件发射器(自定义事件),当数据值改变时发出一个事件,在另一个组件中监听该事件并执行想要的操作。

  3. 如果你的组件之间没有关系,那么你必须使用除上述方法以外的其他方法。你可以使用两个方法:事件总线和状态管理库。对于Vue来说,有一个官方状态管理库叫做VueX,非常容易使用。如果你想使用其他东西而不是Vuex,你可以使用诸如Redux、Mobx等方式。

这份文档包含了你需要了解的所有内容。我不想放任何代码,因为文档已经很清晰了。

VueX是最好的方法!非常容易使用。

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


1

//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>

首先,您需要一个父组件,以便两个组件可以通信。当单击my-button组件时,会触发add-value事件,该事件调用doSomething()函数,然后更新值并将其显示到my-viewer组件中。

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++;
             }
        }
     })

这是基于Vue组件指南的内容。

使用Props将数据传递给子组件(从父到子)

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将循环遍历文章并将数据传递给blog-post组件

         <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>

监听子组件事件(子到父)

HTML

首先,您必须通过v-on:enlarge-text="onEnlargeText"注册事件,以使用$emit并确保它始终设置为小写,否则它将无法正常工作。例如,enlargeTextEnlargetext将始终转换为enlargetext,因此请改用enlarge-text,因为它易于阅读且有效。有关$emit的简要说明,请在这里阅读。

         <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

当用户点击 button 按钮后,v-on:click="$emit('enlarge-text')" 将被触发,随后调用父组件中的 onEnlargeText() 函数。

         //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++;
            }
          }
        })

0

实际上,有时候props很烦人,你可能需要在jquyer中使用一些旧的外部库,只需要传递值。在99%的情况下,使用可以完成工作的props。

A)花费大量时间调试更改大量代码以传递变量 B)一行解决方案

在数据中创建主要变量letmeknow作为对象{}

this.$root.letmeknow

然后在组件代码中的某个地方

this.$root.letmeknow = this;

接着,我在组件控制台使用 console.log( this.$root.letmeknow ),看到现在能够改变一些值了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接