EventBus
以前的时候自己对Vue的了解不够深,总觉得EventBus和vuex是差不多的东西,直到最近全职做了前端才发现自己之前的理解是错的。vuex的场景是跨组件data通讯,EvnetBus是事件通讯,之前子组件调用父组件的父组件需要两层$emit才能实现,兄弟组件之间通讯也是比较难以解决问题,这个时候我们就需要EventBus来帮助我们了
代码
eventBus的设计非常简单,不到50行就可以完成(去掉注释更少了)
export default class EventBus {
constructor () {
// 构造函数
this.callbackMap = {}
}
// 添加事件监听
$on (eventName, callback) {
// 按名字保存所有的回调函数
// 1.判断callbackMap是否保存过相同的事件
if (!this.callbackMap[eventName]) {
this.callbackMap[eventName] = []// 没有,就设置一个保存的容器
}
// 2.将callback放在容器中
this.callbackMap[eventName].push(callback) // 对应的emit事件 添加到 this.callbackMap 对象中 调用自定义的函数即可获取到参数
}
// 触发事件
$emit (eventName, ...rest) {
// 按名字调用保存的所有的回调函数
// 1.按照名字取出所有的回调
const callbackArr = this.callbackMap[eventName]
if (!callbackArr) {
return// 没有监听的回调
}
// 2.一个一个调用回调,并且传参
callbackArr.map(callbackItem => {
callbackItem(...rest) // 根据参数 传入对应的 emit自定义函数中
})
}
$off (eventName, callback) {
if (!eventName) {
// 移除所有事件监听
this.callbackMap = {}
return
}
if (!callback) this.callbackMap[eventName] = [] // 移除指定事件的所有监听
if (callback) {
// 移除指定事件的指定的某一个监听
// 获得所有的回调
const callbackArr = this.callbackMap[eventName]
// 从数组中删除对应的需要移除的事件
this.callbackMap[eventName] = callbackArr.filter(callbackItem => {
return callbackItem != callback
})
}
}
}
注册
// main.js
import $Eventbus from '@/util/eventBus' // 替换为实际上的你的文件地址
// ...
// ...
Vue.prototype.EventBus= new $Eventbus()
new Vue({
el: '#app',
router,
i18n,
store,
$env: getUrlEnv(),
render: (h) => h(App)
})
使用
// someA.vue
// 在此处注册on事件
mouted(){
this.EventBus.$on('take',() => {
// do something
})
this.$once('hook:beforeDestroy', () => {
this.Eventbus.$off('take')
})
}
// 然后你在任意组件内调用 this.EventBus.$emit('take')