简单的观察者模式-demo

<script>
  const EventEmitter = (function () {
    const emitters = [];
    const ONCE_SYMBOL = '$$EMITTER_ONCE';

    class $EventEmitter{
      constructor(isInit) {
        emitters.push(this);
        this.listenrs = {};
        if (isInit) {
          return Object.assign(this, {
            create() {
              return new $EventEmitter();
            },
          });
        }
      }

      isFn(fn) {
        return fn instanceof Function;
      }

      once(evtName, fn) {
        /* 思路一:新开一个数组备份 */
        /* 思路二:fn添加属性 */
        fn[ONCE_SYMBOL] = ONCE_SYMBOL;
        this.on(evtName, fn);
      }

      clearOnce(evtName) {
        const cbs = this.listenrs[evtName];
        for (let i = 0; i < cbs.length; i++) {
          if (cbs[i][ONCE_SYMBOL] === ONCE_SYMBOL) {
            cbs.splice(i, 1);
            i--;
          }
        }
      }

      on(evtName, fn) {
        if (!this.isFn(fn)) return;
        if (this.listenrs[evtName]) {
          this.listenrs[evtName].push(fn);
        } else {
          this.listenrs[evtName] = [fn];
        }
      }

      off(evtName, fn) {
        if (fn && this.listenrs[evtName]) {
          let index = this.listenrs[evtName].findIndex(cb => cb === fn);
          if (index >= 0) {
            this.listenrs[evtName].splice(index, 1);
          }
        } else {
          delete this.listenrs[evtName];
        }
      }

      emit(evtName, root) {
        // 调试信息
        if (root && this === EventEmitter) return console.log('%cEventEmitter已是ROOT', 'color:red;');
        /* root 优先触发 */
        if (root && this !== EventEmitter) {
          EventEmitter.emit(evtName);
        }
        if (this.listenrs[evtName]) {
          this.listenrs[evtName].forEach(cb => cb && cb());
          /* 实现once */
          this.clearOnce(evtName);
        }
      }

      /* 任何一个emitter可以触发 */
      emitAll(evtName) {
        emitters.forEach(emitter => {
          emitter.emit(evtName);
        });
      }
    }

    /* 对外暴露,class内部作为root使用 */
    const EventEmitter = new $EventEmitter(true);
    return EventEmitter;
  })();
  EventEmitter.on('haha', function () {
    console.log('你好');
  });
  EventEmitter.on('haha', function () {
    console.log('你好2');
  });
  EventEmitter.on('root-haha', function () {
    console.log('哈哈,emit by child');
  });
  setTimeout(() => {
    EventEmitter.emit('haha');
  }, 2000);

  const bus1 = EventEmitter.create();
  bus1.on('haha', function () {
    console.log('你好');
  });
  bus1.on('root-haha', function () {
    console.log('root-哈哈');
  });
  bus1.once('haha', function () {
    console.log('once');
  });
  bus1.once('haha', function () {
    console.log('once1');
  });
  bus1.once('haha', function () {
    console.log('once2');
  });
  setTimeout(() => {
    bus1.emit('haha');
    EventEmitter.emit('root-haha', true); // 无效
    bus1.emit('root-haha', true);
  }, 2000);

  const bus3 = EventEmitter.create();
  setTimeout(() => {
    console.log('%c全部触发', 'color:red;');
    bus3.emitAll('haha')
  }, 4000);
</script>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值