0
点赞
收藏
分享

微信扫一扫

JS - 手写实现观察者模式【Observe】

  let Observer = (function () {
    // 定义存储事件的变量
    let data = {};

    // 返回执行函数对象
    return {
      /**
       * @on 定义订阅函数
       * @type 函数类型
       * @callback 订阅回调函数
       **/
      on(type, callback) {
        // 判断当前存储事件变量中是否有该函数类型,有的话,往该函数类型中添加成员,没有的话创建一个新的成员
        data[type] ? data[type].push(callback) : (data[type] = [callback]);
      },

      /**
       * @trigger 订阅发布函数
       * @type 发布函数的类型
       * **/
      trigger(type, ...args) {
        // 判断是否存在该类型函数
        if (!data[type]) throw Error(`${type} 类型函数还没有被订阅`);
        // 如果存在 遍历执行里面的含糊
        data[type].forEach((item) => {
          item(...args);
        });
      },

      /**
       * @off 订阅注销函数
       * @type 注销函数类型
       * @callback 注销的回调函数
       * **/
      off(type, callback) {
        // 判断是否存在该类型函数
        if (!data[type] && callback)
          throw Error(`${type} 类型函数还没有被订阅`);
        // 如果上面的条件成立
        if (callback) {
          // 使用for循环遍历数组成员,使用forEach遍历可能会造成数组塌陷问题
          for (let i = data[type].length; i >= 0; i--) {
            // 如果当前类型内的数组成员和传递的回调相同,则删除该成员
            if (data[type][i] === callback) {
              data[type].splice(i, 1);
            }
          }
          // 判断该类型是否为空 如果为空了 直接删除该类型
          data[type].length > 0 ? '' : delete data[type];
        } else if (data[type]) {
          // 当只传递一个类型的时候 直接删除该类型
          delete data[type];
        } else {
          // 当什么都不传递的时候 直接清空存储函数变量
          data = {};
        }
      },

      /**
       * @once 定义单次订阅函数
       * @type 函数类型
       * @callback 订阅的回调函数
       * ***/
      once(type, callback) {
        // 缓存this
        let _this = this;
        // 定义一个内置函数
        function fn(...args) {
          // 先注销函数
          _this.off(type, fn);
          // 在执行该回调函数
          callback(...args);
        }
        // 订阅函数
        this.on(type, fn);
      },
    };
  })();

  // 定义一个函数
  function demo(x) {
    console.log('demo函数', x);
  }
  function test(x) {
    console.log('test函数', x);
  }

  // 试验1
  // 订阅消息
  /*  Observer.on('demo', demo);
  Observer.on('demo', demo);
  Observer.on('demo', demo);
  Observer.on('demo', test);
  // 发布消息
  Observer.trigger('demo', 100); //  demo函数 100 * 3   test函数 100
  // 注销消息
  Observer.off('demo', demo);
  // 触发消息
  Observer.trigger('demo', 200); // test函数 200 */

  // 试验2
  // 订阅消息
  /*  Observer.on('demo', demo);
  Observer.on('demo', demo);
  Observer.on('demo', demo);
  Observer.on('demo', test);
  // 发布消息
  Observer.trigger('demo', 100); //  demo函数 100 * 3   test函数 100
  // 注销消息
  Observer.off('demo');
  // 发布消息
  //   Observer.trigger('demo', demo); // 报错
  //   Observer.trigger('demo', test); // 报错 */

  // 实现3
  // 订阅消息
  /* Observer.on('demo', demo);
  Observer.on('demo', demo);
  Observer.on('demo', demo);
  Observer.on('demo', test);
  // 发布消息
  Observer.trigger('demo', 100); //  demo函数 100 * 3   test函数 100
  // 注销消息
  Observer.off();
  // 发布消息
  Observer.trigger('demo', demo); // 报错
  Observer.trigger('demo', test); // 报错 */

  // 实现4
  // 订阅消息
  Observer.once('demo', demo);
  // 发布消息
  Observer.trigger('demo', 100); //  demo函数 100 * 3   test函数 100
  Observer.trigger('demo', 100); //  报错
举报

相关推荐

0 条评论