js手写实现eventBus事件总线订阅者发布者模式

EventBus 几个常用方法如下:

eventBus的4个基本事件

on

发布和订阅

emit

执行该订阅下的所有函数

off

取消某个函数的订阅

once

只执行一次订阅事件

这里用Map 存储 EventBus 的数据(发布者-订阅者)。

代码如下:

      // 组件通信,一个触发与监听的过程
      class EventBus {
        constructor() {
          this._events = new Map();//存储发布者和订阅者
        }
        on(type, fn) {//发布和订阅
          //获取到该发布者下的订阅者集合handler
          let handler = this._events.get(type);
          //如果还没有订阅者
          if (!handler) {
            this._events.set(type, [fn]);//加入这个订阅者
          } else {
            handler.push(fn);//直接push进去handler
          }
        }
        emit(type, ...args) {//执行该订阅下的所有函数
          let handler = this._events.get(type);
          for (let i = 0; i < handler.length; i++) {
            handler[i].apply(this, args);//执行第i个订阅者函数
          }
        }
        off(type, fn) {//取消某个函数的订阅
          let handler = this._events.get(type);//获取所有的订阅者
          //数组中订阅者有多个,找到等于fn的订阅者删除
          handler.splice(handler.findIndex(e => e === fn), 1);
        }
        //只执行一次
        once(type, fn) {
          let _self = this;//拿到当前实例对象的this
          function handler() {
            _self.off(type, handler);//删除type下的handler函数
            fn.apply(null, arguments);//执行该函数
          }
          this.on(type, handler)//type下添加handler函数
        }
      }
eventBus的4个基本事件

on

发布和订阅。在type上添加订阅者。

emit

执行该订阅下的所有函数。遍历type下的订阅者,执行。

off

取消某个函数的订阅。在订阅者中找到fn然后删除。

once once方法将handler函数挂载了type这个发布者上,如果执行emit就会执行handler函数中的内容,会先删除type上的所有的函数,然后执行fn。

测试代码:

      //测试用例
      // 下面是 测试代码
      function test1(...params) {
        console.log(11, params)
      }
      function test2(...params) {
        console.log(22, params)
      }
      function test3(...params) {
        console.log(33, params)
      }
      function test4(...params) {
        console.log(44, params)
      }

      let eb = new EventBus()
      //测试
      eb.on('event1', test1)
      eb.on('event1', test2)
      eb.on('event1', test3)
      eb.emit('event1', '第一次');//让挂载在event1下的所有test1,test2,test3全部执行
      //输出11,'第一次'    22,'第一次'  33,'第一次'  
      //取消test1的订阅
      eb.off('event1', test1)
      eb.emit('event1', '第二次')//只输出test2,test3的结果
      eb.once('once', test4);
      eb.emit('once', '执行一次', 1, 2, 3)
      eb.emit('once', '执行二次', 1, 2, 3)

结果:

js手写实现eventBus事件总线订阅者发布者模式_第1张图片

结束!!

你可能感兴趣的:(JavaScript,前端经典面试题,javascript)