事件总线,用来实现非父子组件之间的传值

一、事件总线工作原理

事件总线的原理,就是我们通过new Vue再创建一个新的 Vue 实例对象bus,将该实例作为组件之间传值的桥梁。
当组件 A 想要传值给组件 B 时,步骤如下图所示:
事件总线 - 图1

二、事件总线的使用

首先我们需要在项目中新建一个.js文件,用来创建事件总线,例如src/utils/bus.js

  1. import Vue from 'vue';
  2. const bus = new Vue;
  3. export default bus;

第一步:给 bus 设置事件监听器

由于是组件 B 想要接收数据,因此我们在组件 B 的生命周期函数mounted中给 bus 设置事件监听器:

  1. import bus from '../utils/bus.js'
  2. export default {
  3. // $bus.on应该在created钩子内使用,如果在mounted使用,它可能接收不到其他组件来自created钩子内发出的事件;
  4. mounted() {
  5. bus.$on('getData', data => {
  6. console.log(data); // 组件 A 传递的数据
  7. })
  8. }
  9. }

在组件 B 中引入 bus,并通过$on方法给 bus 设置一个 getData 方法的事件监听器。当 getData 方法被触发时,就会执行箭头函数,并通过 data 接收到传递进来的数据。

第二步:触发 bus 监听的事件

组件 A 负责传递数据,因此在组件 A 的事件触发 bus 监听的事件,并将数据传递过去:

  1. import bus from '../utils/bus.js'
  2. export default {
  3. methods: {
  4. postData() {
  5. bus.$emit('getData', '传递的数据')
  6. }
  7. }
  8. }

postData方法被调用时,组件 A 中就会触发getData方法,并将字符串”传递的数据”传递给组件 B。
至此,我们就通过事件总线实现了组件 A 向组件 B 的传值。

三、注意点

  1. $bus.on应该在created钩子内使用,如果在mounted使用,它可能接收不到其他组件来自created钩子内发出的事件;
  2. $bus.emit应该在mounted中使用,等待created中的$bus.on事件绑定完成;
  3. 发布订阅的事件在beforeDestory钩子里需要使用$bus.off解除,组件销毁后没必要一直监听。