js 模拟实现EventBus

文章原文: https://www.cnblogs.com/yalong/p/14294497.html

EventBus 几个常用方法如下:

  • on
  • emit
  • off
  • once

这里用Map 存储 EventBus 的数据,Map 的模拟实现 可以看 https://www.cnblogs.com/yalong/p/14292024.html
示例代码如下:

  let eb = new EventBus()
  eb.on('event1', test1)
  eb.emit('event1', '第一次')

  eb.off('event1', test1)
  eb.emit('event1', ['第二次1', '第二次2'])

  eb.once('once', test4);
  eb.emit('once', '执行一次', 1, 2, 3)

模拟实现代码如下:

  class EventBus {
    constructor () {
      this._events = new Map(); // 存储事件/回调键值对
    }
 
    // on 监听
    on(type, fn) {
      const handler = this._events.get(type); // 获取对应事件名称的函数清单
      if (!handler) {
          this._events.set(type, fn)
      } else if (handler && typeof handler === 'function') {
          // 如果handler是函数,说明当前只有一个监听者
          // 再次添加监听者,需要改用 数组储存
          this._events.set(type, [handler, fn]);
      } else {
          // 已有多个监听者,直接往数组里push函数即可
          handler.push(fn);
      }
    }
 
    // emit 触发
    emit(type, ...args) {
      let handler = this._events.get(type)

      if (Array.isArray(handler)) {
        // 是数组,说明有多个监听者,需要依次触发里边的函数
        for (let i = 0; i < handler.length; ++i) {
          if (args.length > 0) {
            handler[i].apply(this, args)
          } else {
            handler[i].call(this);
          }
        }
      } else {
        // 单个函数的情况直接触发即可
        if (args.length > 0) {
          handler.apply(this, args)
        } else {
          handler.call(this)
        }
      }
      return true
    }
 
    // off 移除监听
    off(type, fn) {
      const handler = this._events.get(type)
      if (handler && typeof handler === 'function') {
          // 函数,说明只有一个监听者,直接删除就行
          this._events.delete(type)
      } else {
        handler.splice(handler.findIndex(e => e === fn), 1)
      }
    }

    // 单次执行
    once(type, fn) {
      let _self = this
      function handler() {
        _self.off(type, handler)
        fn.apply(null, arguments)
      }
      this.on(type, handler)
    }
  }


  // 下面是 测试代码
  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(params)
    console.log(33, params)
  }

  //测试用例
  let eb = new EventBus()
  eb.on('event1', test1)
  eb.on('event1', test2)
  eb.on('event1', test3)
  eb.emit('event1', '第一次')

  eb.off('event1', test1)
  eb.emit('event1', ['第二次1', '第二次2'])

  eb.once('once', test4);
  eb.emit('once', '执行一次', 1, 2, 3)

console 输出结果如下:

原文地址:https://www.cnblogs.com/yalong/p/14294497.html