在vue项目中自定义事件总线eventHub

由于在工作中vue的项目中使用了大量是全局事件总线广播,使得某些方法在某种情况下被重复多次调用,查看了一下原因,是因为在每个单文件组件中定义的事件接收器和事件广播器在页面销毁的时候没有注销导致的。于是在保证改动量不大的前提下,决定自定义一个全局事件总线文件。

之前的使用是在 main.js 文件中 vue.prototype.$eventHub = vue.prototype.$eventHub || new Vue()

因此,重新定义一个文件 EventHub.js

/**
 * Created by baidm in 2021/1/3 on 12:54
 */
class EventHub {
    constructor(vm) {
        this.vm = vm;
        this.curVm = null;
        this.events = {};
        this.eventMapUid = {};
    }

    /**
     * 注册调用者实例
     * @param vm
     */
    $register(vm) {
        this.curVm = vm;
    }

    /**
     * 收集所有的事件类型
     * @param uid
     * @param type
     */
    setEventMapUid(uid, type) {
        if (!this.eventMapUid[uid]) {
            this.eventMapUid[uid] = [];
        }
        this.eventMapUid[uid].push(type);
    }

    /**
     * 收集每种类型的回调
     * @param type
     * @param fn
     */
    $on(type, fn) {
        if (!this.events[type]) {
            this.events[type] = [];
        }
        this.events[type].push(fn);
        if (this.curVm instanceof this.vm) {
            this.setEventMapUid(this.curVm._uid, type);
        }
    }

    /**
     * 触发每种类型的所有回调
     * @param type
     * @param args
     */
    $emit(type, ...args) {
        if (this.events[type]) {
            this.events[type].forEach(fn => fn(...args));
        }
    }

    /**
     * 取消订阅事件
     * @param type
     * @param fn
     */
    $off(type, fn) {
        if (fn && this.events[type]) {
            const index = this.events[type].findIndex(f => f === fn);
            if (index !== -1) {
                this.events[type].splice(index, 1);
            }
            return;
        }
        delete this.events[type];
    }

    /**
     * 取消uid订阅的所有事件
     * @param uid
     */
    $offAll(uid) {
        const curAllTypes = this.eventMapUid[uid] || [];
        curAllTypes.forEach(type => this.$off(type));
        delete this.eventMapUid[uid];
    }
}

export default {
    install(vm, options = {}) {
        Reflect.defineProperty(vm.prototype, "$eventHub", {
            value: new EventHub(vm)
        })
    }
}

然后在 main.js 文件中定义 mixin

import Vue from 'vue'
...

import EventHub from "./EventHub"

EventHub.install(Vue);

const mixin = {
    data() {
        return {}
    },
    created() {
        this.$eventHub.$register(this);
    },
    methods: {},
    directives: {},
    beforeDestroy() {
        this.$eventHub.$offAll(this._uid);
    }
};
Vue.mixin(mixin);

...

这样在不改变原有代码中的写法 this.$eventhub.$on() 和 this.$eventHub.$emit() 的前提下,即可在每个SFC卸载的时候自动下载在该组件中定义的事件广播。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明致成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值