2022-09-08【实现Event Bus】

87 阅读1分钟

在vue中,对于兄弟组件或者隔代组件我们通常使用Vuex实现组件通信,除此之外还可以使用Event Bus 来实现。Event Bus本质上是发布-订阅模式,在开发中应用广泛。

在vue中使用Event Bus

注册Event Bus

// main.js 
// 本质上EventBus是一个vue实例 一个没有DOM的组件
Vue.prototype.$bus = new Vue()

订阅(接收)事件

// 这里func指someEvent这个事件的监听函数
this.bus.$on('someEvent', func)

发布(触发)事件

// 这里params指someEvent这个事件被触发时回调函数接收的入参
this.bus.$emit('someEvent', params)

自定义实现Event Bus

根据Event Bus的使用方法,我们手动实现一个EventBus,具体分析见注释解析

 class EventBus {
            constructor() {
                //dep 是一个map ,用于存储事件及其回调的对应关系
                this.dep = {}
            }
            //on 用于注册事件,接收事件名称及其回调
            on(eventName, cb) {
                //先检查一下目标事件是否存在
                if (!this.dep[eventName]) {
                    //不存在,初始化一个监听函数队列
                    this.dep[eventName] = []
                }
                this.dep[eventName].push(cb)
            }
            //emit 用于触发目标事件,接收事件名称和函数入参
            emit(eventName, ...args) {
                if (this.dep[eventName]) {
                    // 如果存在 循环调用回调函数
                    this.dep[eventName].forEach((cb) => {
                        cb(...args)
                    })
                }
            }
            //移除事件
            off(eventName) {
                if (this.dep[eventName]) {
                    delete this.dep[eventName]
                }
            }
            //移除事件内指定回调函数
            offCb(eventName, cb) {
                const cbs = this.dep[eventName];
                const index = cbs.indexOf(cb)
                if (index !== -1) {
                    cbs.splice(index, 1)
                }
            }
            //注册单次监听器(即执行完回调函数,自动销毁)
            once(eventName, cb) {
                const cbWrap = (...args) => {
                    cb(...args)
                    this.offCb(eventName, cbWrap)
                }
                //用cbWrap将事件进行包裹,使其执行完毕后,自动销毁
                this.on(eventName, cbWrap)
            }
        }