☀️ Vue 全局事件总线

全局事件总线 GlobalEventBus:一种组件间通信的方式,适用于任意组件间通信。(这不是 Vue 中的 API,是利用现有的功能组合)

要实现这个能给任意组件通信的总线中间件,必须要实现两个条件:

  • 所有的组件都能看见它。
  • 必须要保证它能够调用 $on$off$emit

要保证实现前述的第一个条件,可以考虑要使 vc 组件实例原型对象中能够找到。所以可以利用前述的一个重要关系:组件实例原型与 Vue 实例原型的关系

要保证实现第二个条件,利用生命周期 beforeCreate ,在原型中赋值为组件实例对象。一般写为 Vue.prototrype.$bus = thisthis 为当前创建的 vm ) 。

  • 使用全局事件总线:(在入口文件 main.jsbeforeCreate安装全局事件总线

    new Vue({
    	......
    	beforeCreate() {
    		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    	},
        ......
    }) 
    
    1
    2
    3
    4
    5
    6
    7
    • 使用事件总线:

      • 接收数据:A 组件想要接收数据,就在 A 组件中给 $bus 绑定自定义事件,事件的回调留在 A 组件自身(谁绑定事件,回调在谁身上):

        methods() {
          demo(data) { ... }
        },
        ...
        , mounted() {
          this.$bus.on('xxx', this.demo) // 向全局事件总线绑定自定义事件 xxx
        }
        
        1
        2
        3
        4
        5
        6
        7
      • 提供数据(谁提供数据谁就触发事件):

        this.$bus.$emit('xxx', 数据)
        
        1
      • ⚠️ 最好在接收完数据之后,在 beforeDestory 中用 $off 去解绑当前组件所用到的事件:

        beforeDestroy() {
            this.$bus.$off('xxx')
        },
        
        1
        2
        3
  • 绑定在 $bus 中的自定义事件命名可能会有冲突,所以要注意不要使用已经定义的自定义事件的命名;并且最好不占用这个自定义事件,使用完后就(在绑定处)解绑该自定义事件。
  • 为什么在 beforeDestory 中销毁?组件不使用后销毁后,有可能在 vc 实例中的自定义事件没有被销毁!

🌰 实现全局事件总线例子

  • 首先在入口文件安装全局事件总线。
  • 现在在 School 组件中想要接收来自 Student 组件的数据,所以在 School 组件中绑定自定义事件 hello ,并将回调写在 School 组件中:(下面使用箭头函数)
mounted() {
  this.$bus.$on('hello', (data) => {
    console.log('School receiving StudentName: ', data)
  })
}
1
2
3
4
5
  • Student 组件想要提供数据,则在 Student 中触发该自定义事件 hello ,并且传递数据到参数中。
<button @click="sendStudentName">把学生名给School组件</button>
1
methods: {
  sendStudentName() {
    this.$bus.$emit('hello', this.name)
  }
}
1
2
3
4
5
  • School 组件接受完数据,解绑该自定义事件:
 beforeDestroy() {
  this.$bus.$off('hello')
}
1
2
3
📢 上次更新: 2022/09/02, 10:18:16