vue eventBus实现组件通信

874 阅读1分钟

直接上代码 封装成第三方插件使用

新建文件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属性监听每个值,达到实时消息的功能。具体看看封装的源码,其实很简单,一看就懂。