Vue组件通信

34

我有两个Vue组件:

Vue.component('A', {});

Vue.component('B', {});

我如何从组件B访问组件A?这些组件之间的通信如何工作?


你可以使用全局事件总线来$emit事件,当一个组件发生变化时。当事件被触发时,使用$on来响应这些变化并相应地更新组件。我在这里写了一个教程,介绍如何在三个组件和Google Maps API之间进行通信:https://blog.jscrambler.com/communicating-between-vue-2-components-and-google-maps/ - Connor Leech
6个回答

33
跨组件通信在Vue.js文档中并没有得到太多关注,也没有很多教程涵盖这个主题。由于组件应该是隔离的,因此你永远不应该直接“访问”一个组件。这会将组件紧密地耦合在一起,而这正是你想要避免的。
Javascript有一个出色的通信方法:事件。Vue.js有一个内置的事件系统,主要用于父子通信。来自文档
尽管您可以直接访问Vue实例的子代和父代,但使用内置的事件系统进行跨组件通信更加方便。它还使您的代码更少耦合,更易于维护。一旦建立了父子关系,您就可以使用每个组件的事件实例方法来分派和触发事件。
他们的示例代码用于说明事件系统:
var parent = new Vue({
  template: '<div><child></child></div>',
  created: function () {
    this.$on('child-created', function (child) {
      console.log('new child created: ')
      console.log(child)
    })
  },
  components: {
    child: {
      created: function () {
        this.$dispatch('child-created', this)
      }
    }
  }
}).$mount()

Dan Holloran最近在这篇 文章中谈到了他与跨组件消息传递的“斗争”,如果您需要在没有父子关系的组件之间进行通信,这可能对您有所帮助。

除了使用事件进行通信之外,我还有一种经验丰富的方法,即使用一个中央组件注册表,其中包含对公共API的引用,该API实例绑定到一个组件。注册表处理对组件的请求并返回其公共API。

在Vue.js的上下文中,事件是我的首选。


4
请注意,这种父子组件通信方式将无法在 Vue 2.0 的未来版本中使用,因为 $dispatch$broadcast 已经被废弃。 - hitautodestruct

12
除了pesla的答案之外,还可以查看指南下的建立大规模应用程序的状态管理部分http://vuejs.org/guide/application.html#State_Management。我在这里创建了一个jsfiddle,基于那个指南:https://jsfiddle.net/WarwickGrigg/xmpLg92c/
这种技术也适用于组件:父子、兄弟组件关系等。
var hub = {
  state: {
    message: 'Hello!'
  }
}

var vmA = new Vue({
    el: '#appA',
    data: {
      pState: {
        dA: "hello A" 
    },
    hubState: hub.state
  }
})

var vmB = new Vue({
    el: '#appB',
    data: {
      pState: {
        dB: "hello B"
    },
    hubState: hub.state
  }
})

8

在您的Vue应用程序中,还可以通过创建单个全局事件中心来建立组件之间的通信。像这样:

var bus = new Vue();

现在,您可以创建自定义事件并从任何组件监听它们。

     // A.vue
    // ...
    doThis() {
        // do the job
    
        bus.$emit('done-this');
    }
    
    // B.vue
    // ...
       method:{
             foo: function()
          }
    created() {
        bus.$on('done-this', foo);
    }

更多相关信息可以在官方文档中找到。


顺便提一下,对于多文件组件,bus 需要以某种方式对所有组件可见。我使用全局 Window 变量(据说这是个坏主意),因为我无法以能够正常工作的方式进行 import - WoJ

3

最佳实践是使用propsevents

有许多在线示例,如:

我建议您阅读一些相关主题的内容。

如果组件是同级并且没有父子关系,则值得检查应用程序的架构。

  • AB是否具有父子关系?
  • 是否存在组件C可能是AB的父组件?

如果ABC的子级,请考虑使用propsevents。 另一种方法是使用propssync,这对于表单数据非常有用:


0

对于兄弟组件之间的通信,我发现使用父组件作为事件总线可以使逻辑相当简单。使用$root作为事件总线需要额外的代码来检查可能不是直接兄弟的组件范围。而使用$parent意味着可以控制所发出事件的范围。

以下示例是针对TableHeader组件的。当单击时,它会重新排序表中的数据,其他标题不再处于活动状态,因此不应显示为这样,计算属性cssClass用于此目的。

export default {
    name: 'TableHeader',
    props: ['sort'],
    data() {
        return {
            direction: this.sort
        }
    },
    computed: {
        cssClass() {
            if (this.direction === 'none') return '';
            return (this.direction === 'descending') ? 'headerSortUp': 'headerSortDown';
        }
    },
    methods: {
        clickHeader(event) {
            this.direction = (this.direction === 'none' || this.direction === 'descending') ? 'ascending' : 'descending';

            //We use the parent as an event bus
            this.$parent.$emit('TableHeader:sortChanged', this);
        },
        sortChanged(element) {
            //Dont reset if this is the emitter         
            if (this === element) return; 

            this.direction = 'none';
        }
    },      
    created() {
        this.$parent.$on('TableHeader:sortChanged', this.sortChanged);
    },
    beforeDestroy: function () {
        this.$parent.$off('TableHeader:sortChanged', this.sortChanged)
    }
}

0

在Vuejs组件之间进行通信有很多选项。如果您的组件是父子关系,则应使用“props”将数据从父组件发送到子组件,并使用“events”从子组件向父组件通信。如果您的组件是兄弟关系,则需要使用“store”,否则可以使用“$root”属性。

从父组件到子组件

父组件

<ChildComponent :propsData="dataToPassToChild" />

子组件必须具有属性

props: ['propsData']

子组件到父组件

子组件

this.$emit('messegeToParent', arg1, arg2, ...);

父组件

<ChildComponent @messageToParent="messageReceivedFromChild" />

以下方法应该在子组件中

messageReceivedFromChild(arg1, arg2, ...) {

}

兄弟组件

组件1

this.$root.$emit('message1', arg1, arg2, ...);

组件 2

this.$root.$on('message1', (arg1, arg2, ...) => {

});

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