注册一个
$bus
,使用全局事件总线
实现任意组件间通信!除了Vuex
,本文的全局事件总线
是实现组件间通信的第二种方式。欢迎持续关注新系列文章
[Vue 补洞]
系列,用久了 Vue2 总有一些遗漏的知识点,一起通过该系列文章一起查漏补缺!
实现组件间通信的另外两种方式,建议阅读!
【Vue | 补洞 | 01】Vuex 环境搭建及基本使用
【Vue | 补洞 | 02】mapState 一行代码获取 vuex 所有数据
【Vue | 补洞 | 03】Vuex 模块化编码
【Vue补洞 | 05】消息订阅与发布
1. 作用
用于任意组件间通信
举个简单的例子:原本不认识的两个小年轻,通过媒婆建立起联系,在还没有互加联系方式的情况下,双方要
互通消息
只能借助媒婆。而媒婆之所以能当媒婆,其前提条件是:男女双方都认识媒婆。这在全局事件总线中,也是类似的情况。
2. 适用场景
非父子组件,跨多级进行数据或事件的传递
3. “媒婆” 所需具备的条件
- 所有组件都能访问到该实例上的方法(因此需要将该"媒婆"挂载到
根实例vm
上,其所有子组件就都能访问了) - 能调用到
$on $off $emit
(这些方法都在Vue原型链上,因此"媒婆"得是Vue的实例对象
,要么是vm
,要么是VueComponent
)
4. 使用
1)声明全局事件总线
为何要将
$bus
绑定在beforeCreated
中?
beforeCreated
时还未对数据监测、数据代理等进行挂载,等到创建组件时,在
mounted
中调用了this.$bus.$on
绑定事件,这时$bus
已经存在且可以使用了
// main.js
import Vue from 'vue'
...
new Vue({
...
beforeCreated() {
Vue.prototype.$bus = this
}
})
2)接收方绑定事件
假设:A组件想接收数据,而B组件会触发事件 getName
并传递数据给A,则需要在A组件身上使用 $on
绑定自定义事件,如下:
// A.vue
mounted() {
this.$bus.$on('getName', (value)=>{
console.log(value)
})
}
3)发送方触发事件
在B组件中,通过 $emit
就可以触发在A身上的 getName
事件,并将 name
的值传给A组件
// B.vue
methods: {
xxxx() {
let name = 'Jokerls'
this.$bus.$emit('getName', name)
}
}
4)解绑
最好在组件销毁时,把组件身上 $on
的事件给解绑。(因为 $bus
会一直存在,若不解绑,则会一直占用着总线上的某个方法,导致别的组件 调用同名方法时,会出现冲突)
注意
不能使用 this.$off()
全部解绑,会导致别人在 $bus
身上注册的方法失效。
// A.vue
mounted() {
this.$bus.$on('getName', (value)=>{
console.log(value)
})
},
beforeDestroy() {
this.$off('getName')
}
5. 总结
- 通过
$bus
注册全局时间总线 - 通过
$on
注册事件 - 通过
$emit
触发事件并发送数据 - 通过
$off
解绑事件