手写实现简单的Vue事件总线

31 篇文章 17 订阅

一、什么是事件总线

自定义事件总线属于一种观察者模式,其中包括三个角色:

  • 发布者(Publisher):发出事件(Event);
  • 订阅者(Subscriber):订阅事件(Event),并且会进行响应(Handler);
  • 事件总线(EventBus):无论是发布者还是订阅者都是通过事件总线作为中台的;

当然我们可以选择一些第三方的库:

  • Vue2默认是带有事件总线的功能;
  • Vue3中推荐一些第三方库,比如mitt;

二、手写实现事件总线

当然我们也可以实现自己的事件总线:

  • 事件的监听方法on:存储对应事件名需要执行的事件函数
  • 事件的发射方法emit:执行对应事件名需要执行的事件函数
  • 事件的取消监听off:删除对应事件名需要执行的事件函数
    在这里插入图片描述
    运行结果:
    在这里插入图片描述
// eventBus对象:
// {
//     abc: [
//         {需要监听的函数, 为需要监听的事件函数绑定的this},
//         {需要监听的函数, 为需要监听的事件函数绑定的this}
//     ]
// }
class EventBus {
    constructor() {
        this.eventBus = {}
    }
    /*
    * on函数:
    * 被调用时,需要把eventCallback和thisArg放到一个对象中,然后把这个对象push到一个数组里,
    * 然后把eventName作为key,把这个数组作为value存到eventBus对象中
    * eventName:需要监听的事件名称
    * eventCallback:需要监听的事件函数
    * thisArg:为需要监听的事件函数绑定this
    */
    on(eventName, eventCallback, thisArg) {
        let handlers = this.eventBus[eventName]
        if (!handlers) {
            // 如果在eventBus对象中找不到key为eventName的handlers,
            // 则创建一个handlers空数组,并放到eventBus对象中
            handlers = []
            this.eventBus[eventName] = handlers
        }
        // 如果handlers存在,则把需要监听的eventCallback函数、函数需要绑定的this
        // 以对象的形式存到handlers中
        handlers.push({
            eventCallback,
            thisArg
        })
    }
    /*
    * emit函数:
    * 一旦被调用,则需要执行eventBus对象中key为eventName所对应的的数组中
    * 的每个对象中的eventCallback函数
    */
    emit(eventName, ...payload) {
        // 获取eventBus对象中key为eventName所对应的的数组
        const handlers = this.eventBus[eventName]
        if (!handlers) return
        // 如果数组存在则遍历数组,调用需要执行的事件函数
        handlers.forEach(handler => {
            handler.eventCallback.apply(handler.thisArg, payload)
        })
    }
    /*
    * off函数:
    * 被调用时,删除eventBus中key为eventName,
    * value为一个handler对象,且该对象中的eventCallback属性与off函数第二个参数相等的这个value对象
    */
    off(eventName, eventCallback) {
        // 获取eventBus对象中key为eventName所对应的的数组
        const handlers = this.eventBus[eventName]
        if (!handlers) return
        // 复制handlers,然后使用newHandlers新数组来进行遍历,确保遍历的数组是始终保持不变的
        // 防止出现后续删除某个handlers数组中的对象后,在进行遍历时出现问题
        const newHandlers = [...handlers]
        // 遍历newHandlers
        for (let i = 0; i < newHandlers.length; i++) {
            // 获取newHandlers中的每个handler
            const handler = newHandlers[i]
            // 如果handler的eventCallback 等于 参数中传进来的eventCallback,
            // 则获取到这个handler对象在handlers数组中的下标,然后删除这个handler对象
            if (handler.eventCallback === eventCallback) {
                const index = handlers.indexOf(handler)
                handlers.splice(index, 1)
            }
        }
    }
}


// 以下为测试代码:
const eventBus = new EventBus()

// main.js文件
eventBus.on('abc', function (payload) {
    console.log('监听abc事件', this, payload)
}, {name: 'zep'})

const handleCallback = function (payload) {
    console.log('监听abc事件', this, payload)
}
eventBus.on('abc', handleCallback, {name: 'lala'})

// utils.js文件
eventBus.emit('abc', 123)

eventBus.off('abc', handleCallback)
eventBus.emit('abc', 123)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue事件总线是一种在组件之间进行通信的机制,它允许一个组件触发事件并让其他组件监听和响应这些事件。如果你想手写一个简单Vue事件总线,可以按照以下步骤进行: 1. 创建一个新的Vue实例作为事件总线: ```javascript // eventBus.js import Vue from 'vue'; const eventBus = new Vue(); export default eventBus; ``` 2. 在需要通信的组件中,导入事件总线并使用它: ```javascript // ComponentA.vue import eventBus from './eventBus'; export default { methods: { handleClick() { // 触发自定义事件,并传递数据 eventBus.$emit('customEvent', data); } } } ``` 3. 在需要监听事件的组件中,导入事件总线并使用它: ```javascript // ComponentB.vue import eventBus from './eventBus'; export default { created() { // 监听自定义事件 eventBus.$on('customEvent', this.handleCustomEvent); }, destroyed() { // 在组件销毁时取消事件监听 eventBus.$off('customEvent', this.handleCustomEvent); }, methods: { handleCustomEvent(data) { // 处理接收到的数据 } } } ``` 通过以上步骤,你就可以手写一个简单Vue事件总线。在需要通信的组件中,使用`eventBus.$emit`来触发自定义事件,并可以传递数据;在需要监听事件的组件中,使用`eventBus.$on`来监听自定义事件,并在事件触发时执行相应的处理函数。记得在组件销毁时使用`eventBus.$off`来取消事件监听,以避免内存泄漏。 请注意,手写Vue事件总线是一个简单实现,它没有考虑到一些高级功能,如命名空间、多个事件总线实例等。如果需要更复杂的功能,可以考虑使用第三方插件或使用Vuex进行状态管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值