直接上代码 封装成第三方插件使用
新建文件eventBus.js
import Vue from "vue";
class EventBus{
constructor(vue){
if(!this.handles){
Object.defineProperty(this,"handles",{
value:{},
enumerable:false
})
}
this.Vue=vue;
this.eventMapUid={};
}
setEventMapUid(uid,eventName){
if(!this.eventMapUid[uid]){
this.eventMapUid[uid]=[]
}
this.eventMapUid[uid].push(eventName);
}
$on(eventName,callback,vm){
if(!this.handles[eventName]){
this.handles[eventName]=[]
}
this.handles[eventName].push(callback);
if(vm instanceof this.Vue){
this.setEventMapUid(vm._uid,eventName)
}
}
$emit(){
let args=[...arguments];
let eventName=args[0];
let params=args.slice(1);
if(this.handles[eventName]){
let len=this.handles[eventName].length;
for(let i=0;i<len;i++){
this.handles[eventName][i](...params);
}
}
}
$offVmEvent(uid){
let currentEvent=this.eventMapUid[uid]||[];
currentEvent.forEach(event=>{
this.$off(event)
})
}
$off(eventName){
delete this.handles[eventName]
}
}
let $EventBus={};
$EventBus.install=()=>{
Vue.prototype.$eventBus=new EventBus(Vue);
Vue.mixin({
beforeDestroy() {
this.$eventBus.$offVmEvent(this._uid);
}
})
};
export default $EventBus;
项目根目录main.js文件引入eventBus
import Vue from "./vue"
import eventBUs from "./server/eventBus"
Vue.use(eventBUs);//插件的方式引入
组件使用
//在需要接受消息组件中的mounted中注册消息通道
mounted(){
let vm=this; //这里需要把保存this的作用域,因为在消息通道中有时候this会获取不到
//第一个参数是key 唯一性 一个通道一个key
//有可能一个消息发出点几个组件接受 和订阅消息一个概念
//第二个参数就是接受到的数据
//第三个参数,传入this,当前组件销毁时候,消息通道会跟着销毁,如果一直不使用组件销毁消息通道依然存在,会造成内存泄漏
this.$eventBus.$on('some-message',(data)=>{
console.log(data) //嘿嘿嘿
},vm)
}
//传数据
methods:{
//module需要和接受时候的一样
this.$eventBus.$emit('some-message',"嘿嘿嘿")
}
原理其实就是全局生成一个对象{},注册消息对应key,value,通过Object.defineProperty属性监听每个值,达到实时消息的功能。具体看看封装的源码,其实很简单,一看就懂。