Vue组件通信

Vue components communication

本文关键字:通信 组件 Vue      更新时间:2023-09-26

我有两个Vue组件:

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

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

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

在Vue.js的上下文中,事件将是我选择的武器。

除了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
  }
})

组件之间的通信也可以通过在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);
    }

有关这方面的更多信息,请参阅官方文件。。

最好使用propsevents

网上有很多例子,比如:

  • https://v2.vuejs.org/v2/guide/components.html
  • https://alligator.io/vuejs/component-communication

我推荐一些关于这个主题的读物。

如果组件是兄弟组件,并且没有父子关系,那么检查应用程序的架构可能是值得的。

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

如果ABC的子级,请考虑使用道具和事件。另一种方法是使用propssync,这对表单数据有帮助:

  • https://medium.com/front-end-hacking/vues-v-model-directive-vs-sync-modifier-d1f83957c57c

对于兄弟姐妹之间的通信,我发现使用父节点作为事件总线会使逻辑变得相当琐碎。使用$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)
    }
}

两个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, ...) => {
});