vue2实现兄弟组件的传值-eventBus事件总线

324 阅读1分钟

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的灾难,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。 在本地创建目录vue-bus,在其文件下创建vue-bus.js文件。vue-router 和 Vuex 一样,给Vue添加一个属性bus,并代理emit, on,off三个方法。

vue3.x实现兄弟组件的传值eventBus -- mitt用法

在src下创建一个eventBus.js文件

import Vue from 'vue'
//存储所有的事件
const EventStore = {}
const Bus = new Vue()

const destroyHandler = function () {
    // this 为调用此方法的vue组件
    // eslint-disable-next-line no-invalid-this
    const currentEventobj = EventStore[this._uid]

    //如果是动态组件,需要判断是否是属于同一个组件
    if (!currentEventobj) {
        return
    }
    //eslint-disable-next-line guard-for-in
    for (const type in currentEventobj) {
        const key = Array.isArray(type) ? type.join(',') : type

        //Bus 解绑事件
        Bus.$off(type, currentEventobj[key])
    }
    //删除记录的事件集合
    // eslint disable next-line no-invalid-this
    delete Eventstore[this._uid]
}

const EventBus = (vm) => {
    //获取当前组件实例的destoryed生命周期
    const destroyed = vm.$ptions.destroyed
    // 获取当前组件实例的uid
    const uid = vm._uid
    EventStore[uid] = {}

    !destroyed.includes(destroyHandler) && destroyed.push(destroyHandler)

    return {
        $on: (type, handler) => {
            const key = Array.isArray(type) ? type.join('') : type

            if (!EventStore?.[uid]?.[key]) {
                EventStore[uid][key] = handler
                Bus.$on(type, handler)
            }
        },
        $off: (type, handler) => {
            if (!type) {
                Object.keys(EventStore).forEach((id) => {
                    delete EventStore[id]
                })
                Bus.$off()
                return
            }
            const key = Array.isArray(type) ? type.join(',') : type
            //删除对应的事事件
            delete EventStore[uid][key]
            Bus.$off(type, handler)
        },
        $once: (...params) => Bus.$once(...params),
        $emit: (...params) => Bus.$emit(...params),
    }
}
// 这两行是允许bus不调用依然能够触发emit和once
EventBus.$emit = (...params) => Bus.$emit(...params)
EventBus.$once = (...params) => Bus.$once(...params)

export default EventBus

兄弟组件1-demo1

import EventBus from '@eventBus.js'


beforeDestroy(){
    EventBus(this).$off('cancle_checked')
}

mounted(){
    EventBus(this).$on('cancle_checked',(row)=>{
        ...
    })
    this.getData()
}

methods:{
    getData(){
        const {data} = getDataAip()
        EventBus(this).$emit('update_fields_data',{data:data})
    }
}

兄弟组件2-demo2

beforeDestroy(){
    EventBus(this).$off('update_fields_table')
}

mounted(){
    // 获取demo1中的update_fields_data数据
    EventBus(this).$on('update_fields_data',({data})=>{
        this.fieldsData = data
    })
    // 选中更新table数据
    EventBus(this).$on('update_fields_table',({data,checkedKeys,isCheck})=>{
        ...
    })
}

methods:{
    handleChange(index){
        const checkedItem = this.form[index]
        EventBus(this).$emit('cancle_checked',checkedItem)
    }
}

需要注意在mounted使用on,需要在beforeDestroyon,需要在beforeDestroy中off解除,销毁,因为销毁后,就没必要把监听的句柄存储在bus。

参考文献