struggleForLife

Sometimes your whole life boils down to one insane move.

导航

基于ES6封装发布订阅模式

代码如下:  

封装自定义:subscribe.js

let _subscribe = (function () {
  // Sub 发布订阅类
  class Sub {
    constructor () {
      // 创建一个事件池 用来存储后期需要执行的方法
      this.$pond = [];
    }
    // 向事件池中追加方法(需要做去重处理)
    add (func) {
      let flag = this.$pond.some(item => {
        return item === func;
      });
      !flag ? this.$pond.push(func) : null;
    }
    // 从事件池中移出方法
    remove (func) {
      let $pond = this.$pond;
      for (let i = 0; i < $pond.length; i ++) {
        let item = $pond[i];
        if (item === func) {
          // 移出  (顺序不变的情况下只能用splice了)  但是不能这样写
          // 这样会导致数组塌陷,我们移出不能真移出,只能把当前项赋值为null
          // $pond.splice(i,1);
          $pond[i] = null;
          break;
        }
      }
    }
    // 通知事件池中的方法,按照顺序依次执行;
    fire (...args) {
      let $pond = this.$pond;
      for (let i = 0; i < $pond.length; i ++) {
        let item = $pond[i];
        if (typeof item !== 'function') {
          // 此时再删除
          $pond.splice(i,1);
          i--;
          continue;
        }
        item.call(this,...args);
      }
    }
  }
  // 暴露给外面用
  return function subscribe () {
    return new Sub();
  }
})();
导入使用:
<div class="box" id="box" style="width: 100px; height: 100px; margin: 0 auto; background: seagreen;"></div>
<script>
   let pond = _subscribe();
  document.getElementById('box').onclick = function (ev) {
    pond.fire(ev);
  }
  let f1 = function () {
    console.log(1);
  }
  let f2 = function () {
    console.log(2);
    pond.remove(f1);
  }
  let f3 = function () {
    console.log(3);
  }
  let f4 = function (ev) {
    console.log(4,ev);
  }
  pond.add(f1);
  pond.add(f2);
  pond.add(f3);
  pond.add(f4);
</script>

posted on 2020-02-24 11:59  struggleForLife  阅读(681)  评论(0编辑  收藏  举报