• 事件总线--EvenBus


    什么是事件总线

    事件总线是实现基于事件驱动模式的方式之一,事件发送者将事件消息发送到一个事件总线上,事件订阅者向事件总线订阅和接收事件,然后再处理接收到的事件。当然,订阅者不仅可以接收和消费事件,它们本身也可以创建事件,并将它们发送到事件总线上。

    事件总线是对发布-订阅模式的一种实现。它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需要相互依赖,达到一种解耦的目的。

    实现

    我们如果想要实现一个自定义的EventBus,那么首先就需要明白需要实现什么功能:

    1. on(eventKey, callback):新增事件监听器,可以一个eventKey绑定多个callback,使用emit来触发指定eventKey的所有callback
    2. once(eventKey, callback):监听一个自定义事件,但是只会执行一次,执行完毕后当前事件监听器会被移除
    3. off([eventKey, callback]):参数eventKey和callback都是可选的,
    • 如果没有提供参数,则移除所有的事件监听器
    • 如果只提供了eventKey,则移除该事件所有的监听器
    • 如果同时提供了eventKey和callback,则只移除这个回调的监听器
    1. emit(eventKey, […args]):触发指定的事件,附加参数都会传给监听器回调。如果执行的是once定义的监听器,则执行后将会移除该监听器

    具体实现

    • on和once是用来注册函数的,并将其保存到数组中,因为要维持插入顺序和执行顺序一致
    • emit根据key值找到存放回调函数的数组,并执行数组里面的所有函数,可以传入额外的参数
    • off则根据传入的参数,也可能不传参数,找到函数并删除
    class EventBus {
         constructor() {
             this.events = {}; // 初始值为空对象
         }
         //订阅事件
         on(eventKey, fn, isOnce = false) {
             const events = this.events; // 引用赋值
             if (events[eventKey] == null) {
                 events[eventKey] = []; // 初始化eventKey对应的fn数组
             }
             // 将函数添加到数组中
             events[eventKey].push({fn,isOnce});
         }
         //订阅事件,只会执行一次
         once(eventKey, fn) {
             // 代码复用
             this.on(eventKey, fn, true);
         }
         //取消订阅
         off(eventKey, fn) {
             // 如果传入了函数,但是未指定eveneky,直接不执行
             if (!eventKey && fn) return;
             if (!eventKey && !fn) {
                 // 如果未传入参数,则清除所有绑定的函数
                 this.events = {};
             } else if (eventKey && !fn) {
                 // 解绑当前eventKey对应的函数
                 this.events[eventKey] = [];
             } else {
                 // 解绑eventKey和fn对应的函数
                 if (this.events[eventKey]) {
                     this.events[eventKey] = this.events[eventKey].filter(item => item.fn !== fn);
                 }
             }
         }
         //发布事件
         emit(eventKey, ...args) {
             const fnList = this.events[eventKey]; // 引用赋值
             if (fnList == null) return;
             this.events[eventKey] = fnList.filter(item => {
                 const {fn,isOnce} = item;
                 fn(...args); // 执行函数,并传入额外参数
                 if (!isOnce) return true; // 如果不是once,表示后续还可以继续被执行
                 return false; // 如果是once,表示执行一次后就要被过滤掉
             })
         }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    参考博客:
    小猪课堂
    诸葛小愚

  • 相关阅读:
    电商行业少不了的营销方式——邮件营销
    一个反序列化问题引发的思考
    Spring源码:Spring源码阅读环境搭建
    WPF-后台设置控件Background
    助力工业数字化!TDengine 与恩菲 MIM+ 工业互联网平台实现兼容性互认
    Java进程退出
    前端新手导航页--vue3--vue3-tour使用
    【Python】字符串详解
    Qt+树莓派4B 手动设置系统日期和时间
    DDR4 眼图测试方法
  • 原文地址:https://blog.csdn.net/qq_43178432/article/details/126712140