一、理解
全局事件总线:任意组件间通信,原理如下图
x组件需要满足的条件:
1. 所有组件(VC)都能看到x组件
2. 可以调用$on、$off、$emit
为满足条件一,要让所有vc都能看到,需要把x放到构造函数VueComponent的原型上,但是VueComponent是在调用Vue.extend()时产生的,我们每次调用Vue.extend()都会产生新的VueComponent构造函数,所以这是行不通的。但是Vue在产生VueComponent构造函数时,将其原型的隐式原型指向了Vue的原型上(如下图所示),因此我们可以将x放到Vue的原型上。
$on/$off/$emit/$once等方法都存在与Vue的原型对象上,为满足条件2,x应该能访问到Vue的原型对象,所以x应该是vm 或者 vc
二、实现
a. 在main.js中,用vc实现
const Vc = Vue.extend({})
const vc = new Vc()
Vue.prototype.x = vc // Vue.prototype.$bus = vc
b. 在main.js中,用vm实现
new Vue({
el: '#app',
render: h => h(App),
beforeCreate(){
Vue.prototype.$bus = this // 安装全局事件总线
},
})
c. 新建bus.js,用vm实现,此方法,哪个组件用到,就在哪个组件引入
import Vue from 'vue'
export default new Vue()
三、应用
1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods: {
demo(data){......}
},
mounted(){
this.$bus.$on('xxx', this.demo)
},
//或者
import bus from '@/util/bus'
bus.$on('xxx', this.demo)
2. 提供数据:this.$bus.$emit('xxx', 数据) 或者 bus.$on('xxx', this.demo)
四、注意
1. 有可能出现事件命名冲突;
2. 组件销毁前记得解绑$bus绑定的事件
beforeDestroy(){
this.$bus.off('xxx') //xxx为事件名;若()内啥也不写,所有$bus绑定的事件全部取消
},