手写发布订阅(Javascript)

一、基于事件池的发布订阅

class EventEmitter {
      constructor() {
        // 1、创建一个事件池数组
        this.$pond = [];
      }
      // 2、on函数,是将事件添加到事件池中
      on(funName, fun) {
        // 事件池需要进行去重操作
        // let flag = this.$pond.includes({name: funName, fun: fun});
        let flag = false;
        this.$pond.forEach(item => {
          if(item[name] === funName && item[fun] === fun) {
            flag = true;
          }
        });
        if(!flag) {
          this.$pond.push({name: funName, fun: fun});
        }
      }
      // 3、off函数,从事件池中,删除指定的函数
      off(funName, fun) {
        let $pond = this.$pond;
        for(let i=0; i<$pond.length; i++) {
          if($pond[i][name] === funName && $pond[i][fun] === fun) {
            $pond[i][fun] = null;//做这一步,是为了后面做 防止数组塌陷 的过程做铺垫(防止数组塌陷见emit函数)
          }
        }
      }
      // 3、emit函数,从事件池中,执行指定的函数
      emit(funName, fun) {
        let $pond = this.$pond;
        for(let i=0; i<$pond.length; i++) {
          if(typeof $pond[i][fun] === 'function' && $pond[i][name] === funName && $pond[i][fun] === fun) {
              $pond[i][fun].call(this);
          }else if($pond[i][fun] === null) {
            $pond.splice(i, 1);
            i--;//这样做,是为了防止数组塌陷,先--,后++,这样原本的数组下标值不变
          }
        }
      }
      // 4、once函数,fun函数执行一次,就会从事件池中清除
      once(funName, fun) {
        // 定义fn函数,作为中间媒介函数,当fn函数执行后,fun就会从事件池清除
        let fn = (...args) => {
          fun.apply(this, args);
          this.off(funName, fun);
        }
        this.on(funName, fn);
      }
    }

二、普通的发布订阅

class EventBus {
  constructor() {
    this.map = {} 
  }
  on(type, handler) {
    this.map[type] = (this.map[type] || []).concat(handler)
  }
  off(type, handler) {
    if(this.map[type]) {
      if(!this.map[type].length) {
        delete this.map[type]
      } else {
        let index = this.map[type].indexOf(handler)
        this.map[type].splice(index, 1)
      }
    }
  }
  fire(type, data) {
    this.map[type] && this.map[type].forEach(handler => handler(data))
  }
  once(type, handler) {
    let fn = (...args) => {
      handler.apply(this, args);
      this.off(type, handler);
    };
    this.on(type, fn);
  }
}

let eventBus = new EventBus()

eventBus.on('click:btn', data => {
  console.log(data)
})

eventBus.fire('click:btn', {a: 1, b: 2})//{ a: 1, b: 2 }
eventBus.off('click:btn')//销毁后,无结果
eventBus.fire('click:btn', {a: 1, b: 2})//无返回

eventBus.once('click:div', data => {
  console.log(data);
})

eventBus.fire('click:div', {name: 'miracle', age: 21});//{ name: 'miracle', age: 21 }
eventBus.fire('click:div', {name: 'soar', age: 21});//无返回

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值