使用JavaScript实现简单的EventBus

本文详细介绍了EventBus的概念及其在编程中的应用,并提供了一个简单的实现案例。通过对比公共汽车的运行方式,阐述了EventBus作为一种发布订阅模式的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EventBus是什么?

  • event值得是事件 bus 指的是公共汽车

    用公共汽车的固定的站点, 处理上下车的事件, 来比做订阅与事件的分发

  • 在编程中的eventbus通常是用来, 一发布 订阅的方式来传递数据的.

    预先订阅事件, 当事件触发时可以接收大事件相关的数据

  • 如何实现

    需要用到的基础知识

    原型对象与原型链, 回调函数

    基础实现思路:

    1. 准备一个类或构造函数, 用来存放, 事件和订阅者信息

    2. 在该类/构造函数的原型上添加发布和订阅的方法

      • 发布的方法需要传入, 要发布的事件名称, 事件的数据作为参数

      • 订阅方法需要传入, 订阅的事件名称, 事件的处理函数(回调函数)

    3. 主要流程, 通过构造函数的实例, 调用其原型链上的 订阅方法, 传入订阅的事件和方法, 存储区该实例对应属性中(这里用Map)--消息发布者, 通过传入的事件名称, 在实例的数据中取出订阅这先前传入的订阅函数, 并调用, 同时将发布的信息内容, 传入即可


    实现方法: 这里我们用构造函数的语法糖 class

     class _EventBus {
       constructor() {
         //当实例化_EventBus时, 构造函数内的实例属性
         this._events = new Map() //这里使用 map 的 k-v分别储存 事件名-对应的订阅者信息
         //constructor中都有 prototype属性, 该属性指向构造函数, 
         //所以prototype上的方法可以访问实例上的属性
       }
     }

    下面我们在原型对象上添加发布者方法

     // 发布 
     //type为发布的信息名称
     //...args为发布的信息内容, 表示可以接收多个, 最终会以数组形式存入args
     _EventBus.prototype.myPub = function (type, ...args) {
       //根据发布的事件名称获取对应的订阅者(们,这里我们为了可以有多个订阅者采用数组形式)
       let subEvents = this._events.get(type)
       //如果有, 那么遍历所有订阅者信息, 调用订阅者的方法发布信息
       //注意: 这里会给所有的同一信息订阅者发布信息, 
       //如果需要定制化, 可以订阅者打上唯一标识, 并作为发布的检索条件(就是再嵌套一层Map)
       if (subEvents) {
         //这里使用len以便减少动态的获取数组长度
         for (let i = 0, len = subEvents.length; i < len; i++) {
           if (args.length > 2) { //如果传入参数超过两个, 那么我们使用apply
             subEvents[i].apply(this, args) //使用apply直接传入数组
           } else {
             subEvents[i].call(this, ...args) //使用call原地打散
             //(注意: 如果数组存有深层次的对象, 这里只能实现浅拷贝)
           }
         }
       } else { //如果没有该事件, 添加一个, 订阅者为null
         this._events.set(type, null)
       }
     }

    下面在原型上添加订阅的方法

     // 订阅
     //type为发布的信息名称
     //subEvent为订阅时, 存储再实例属性中的处理函数(回调函数, 会在发布时执行该回调)
     _EventBus.prototype.mySub = function (type, subEvent) {
       //获取type类型的处理, 如果没有, 则添加订阅
       const subEvents = this._events.get(type)
       if (!subEvents) {
         //如果type事件没有对应的发布方法, 那么就把订阅的方法传给发布者
         //这里采用数组的形式, 如果有多个订阅者
         this._events.set(type, [subEvent])
       } else {
         subEvents.push(subEvent) // 如果已有订阅者则, 直接追加
       }
       return subEvent //将该方法返回最用会用来移除指定的订阅者
     }

    下面可以简单的使用了

     // 实例化
     const _eb = new _EventBus()
     // 订阅
     //参数的个数和发布的一致哦(少了接收的介绍, 多出来显示 undefined)
     _eb.mySub('eventName', (n1, n2, n3) => {
       console.log(n1, n2, n3)
     })
     _eb.mySub('evebtAge', age => {
       console.log(`接收到的年龄是 ${age}`)
     })
     ​
     // 发布消息
     _eb.myPub('eventName', 'Tom', 'Jerry', 'Tang') //Tom Jerry Tang
     _eb.myPub('evebtAge', 18) //接收到的年龄是 18

    下面我们尝试实现删除订阅事件

     //移除订阅
     //subEvent是调用订阅函数 mySub 时返回的, 传入函数本体, 我们要把它揪出来删掉
     _EventBus.prototype.removeSub = function (type, subEvent) {
       //获取对应消息的所有订阅者信息
       const subEvents = this._events.get(type)
       // 遍历, 找出对应的subEvent 删除
       for (let i = 0, len = subEvents.length; i < len; i++) {
         if (subEvents[i] === subEvent) { //如果mySub返回值使用定义的变量直接接收, 这里是全等
           subEvents.splice(i, 1) //从i开始, 删除1个
           return true //结束
         }
       }
     }

    以上就是我大概理解的事件发布-订阅机制, 如有差误之处, 还望给大佬指点

    附上一个我的麻瓜例子, 可以直接使用, 一看就明白的那种在Vue中的使用

    https://github.com/zdShi/da-event-bus

参考文章:

面试官:既然React/Vue可以用Event Bus进行组件通信,你可以实现下吗? - 掘金

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值