是上一篇的延续,因为在Vue3中去掉了实例的$on和$off方法。本次,我们将实现一个EventBuswidget,并将其封装成一个类,方便调用。单例模式在一个vue应用中,我们只需要这个类的单例模式来管理事件,所以它应该是这样的:classListener{constructor(){this.name="Listener"this.store={}}staticgetInstance(){if(!Listener.instance){Listener.instance=newListener()}returnListener.instance}/***同一个事件可以注册多次,触发时可能执行多次*@paramevtName*@paramcb*/$on(evtName,cb){if(typeofcb!=='function'){console.error(`[${this.name}]无法监听事件:${evtName},cb不是函数`)return}if(!(evtNameinthis.store)){this.store[evtName]=[]}this.store[evtName].push(cb)console.log(`[${this.name}]监听事件:${evtName},cb:${cb.name}`)}$emit(evtName,...data){if(evtNameinthis.store){this.store[evtName].forEach(cb=>{cb(...data)})}else{console.error(`[${this.name}]couldnotfoundevent:${evtName}`)}}/***卸载一个事件,如果没有传入cb,会被所有cb清空*@paramevtName*@paramcb*/$off(evtName,cb){if(evtNameinthis.store){if(cb){constindex=this.store[evtName].indexOf(cb)if(index>-1){this.store[evtName].splice(index,1)console.log(`[${this.name}]移除事件:${evtName}cb:${cb.name}`)}return}deletethis.store[evtName]console.log(`[${this.name}]deletedevent:${evtName}`)returnnull}console.warn(`[${this.name}]event:${evtName}notexist`)}}exportconstVueListener={install:(Vue)=>{Vue.prototype.$listener=Listener.getInstance()}}exportconstMyListener=Listener.getInstance()从最后的export可以看出代码,我们可以把它当作Vue插件,也可以当作js库npm安装为了方便安装使用,我已经在npm官网发布了,可以直接添加到项目依赖中使用listener_leonpmilistener_leo--save//oryarnaddlistener_leo使用方法:importVuefrom'vue'importVueListenerfrom'listener_leo'Vue.use(VueListener)可以在这样的组件中使用:this.$listener.$emit()this.$listener.$on()this.$listener.$off()
