当前位置:   article > 正文

JS/TS笔记学习2

JS/TS笔记学习2

周末总得学点什么吧~
奥利给!
设计模式: 事件订阅派发模式
简单说就是:事件调度中心,负责接收事件发布者的消息,并将这些消息分发给所有订阅了该事件的订阅者

为什么用它,在构建大型、复杂或交互性强的应用程序时,用该模式非常方便,解耦以及提高灵活性方便管理等,下方举例:js 事件分发的使用和扩充

事件分发管理

  • 事件分发基础管理
    最基本的事件分发管理,下方有扩充
class EventDispatcher {
  static events: { [key: string]: any[] } = {};

  // 绑定事件
  static on(eventName: string, callback: Function) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  // 移除事件
  static off(eventName: string, callback: Function) {
    if (this.events[eventName]) {
      const index = this.events[eventName].indexOf(callback);
      if (index !== -1) {
        this.events[eventName].splice(index, 1);
      }
    }
  }

  // 触发事件
  static emit(eventName: string, ...args) {
    if (this.events[eventName]) {
      this.events[eventName].forEach((callback) => {
        callback(...args);
      });
    }
  }
}

// 绑定事件处理函数
EventDispatcher.on("customEvent", (message) => {
  console.log("Received custom event:", message);
});

// 触发事件
EventDispatcher.emit("customEvent", "Hello, World!");

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在这里插入图片描述

如果涉及到target this的指向的话,可以通过apply来操作target指向

  • 加入target指向
class EventDispatcher {
    static readonly events: { [key: string]: any[] } = {};

  /**
   * 绑定事件
   * @param {string} eventName 监听事件 
   * @param {function} callback 监听函数
   * @param {object} target 监听目标
   */
  static on(eventName: string, callback: Function,target: any) {
    const objHandler: {} = {callback: callback, target: target};
    let handlerList: Array<any> = this.events[eventName];
    if (!handlerList) {
        handlerList = [];
        this.events[eventName] = handlerList;
    }
    handlerList.push(objHandler);
  }

  // 移除事件
  static off(eventName: string, callback: Function,target: any) {
    const list = this.events[eventName];
    if (list) {
        for (let i = 0; i < list.length; i++) {
            const oldObj = list[i];
            if (oldObj.callback === callback && (!target || target === oldObj.target)) {
                list.splice(i, 1);
                break;
            }
        }
    }
  }

  // 触发事件
  static emit(eventName: string, ...args) {
    if (this.events[eventName]) {
      this.events[eventName].forEach((objHandler) => {
        if (objHandler.callback) {
            objHandler.callback.apply(objHandler.target, args);
        }
      });
    }
  }

  /**
   * 销毁全部事件分发
   */
  static destroyAll():void{
    //销毁方法1
    for (const eventName in this.events) {  
        if (this.events.hasOwnProperty(eventName)) {  
            this.events[eventName].length = 0;  
            delete this.events[eventName];
        }  
    }
    //销毁方法2 这个比较暴力
    // (this.events as any) = {};
  }
}

// 绑定事件处理函数
EventDispatcher.on("customEvent", (message) => {
  console.log("Received custom event:", message);
},this);

// 触发事件
EventDispatcher.emit("customEvent", "Hello, World!");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

有没有发现当使用了off移除时间并没有删除
因为用的是钩子函数判断不匹配也就删除不了,下方解决:
在这里插入图片描述
除了上面target this指向还可以扩展更高级的处理如优先级,一次性事件和阻止事件冒泡等功能

  • 添加优先级处理
    多加入一个sort进行排序
class EventDispatcher {
  static readonly events: { [key: string]: any[] } = {};

  /**
   * 绑定事件
   * @param {string} eventName 监听事件
   * @param {function} callback 监听函数
   * @param {object} target 监听目标
   * @param {number} priority 事件处理优先级
   */
  static on(
    eventName: string,
    callback: Function,
    target: any,
    priority: number = 0
  ) {
    const objHandler: {} = { callback, target, priority };
    let handlerList: Array<any> = this.events[eventName];
    if (!handlerList) {
      handlerList = [];
      this.events[eventName] = handlerList;
    }
    handlerList.push(objHandler);
    handlerList.sort((a, b) => b.priority - a.priority); // 按优先级降序排序
  }

  // 移除事件
  static off(eventName: string, callback: Function, target: any) {
    const list = this.events[eventName];
    if (list) {
      for (let i = 0; i < list.length; i++) {
        const oldObj = list[i];
        if (
          oldObj.callback === callback &&
          (!target || target === oldObj.target)
        ) {
          list.splice(i, 1);
          break;
        }
      }
    }
  }

  // 触发事件
  static emit(eventName: string, ...args) {
    if (this.events[eventName]) {
      this.events[eventName].forEach((objHandler) => {
        if (objHandler.callback) {
          objHandler.callback.apply(objHandler.target, args);
        }
      });
    }
  }

  /**
   * 销毁全部事件分发
   */
  static destroyAll(): void {
    //销毁方法1
    for (const eventName in this.events) {
      if (this.events.hasOwnProperty(eventName)) {
        this.events[eventName].length = 0;
        delete this.events[eventName];
      }
    }
    //销毁方法2 这个比较暴力
    // (this.events as any) = {};
  }
}
function customEventHandle1(message) {
  console.log("这个优先级设置是0,所以优先级靠后:", message);
}
function customEventHandle2(message) {
  console.log("这个优先级设置是1,所以优先级靠前:", message);
}
// 绑定事件处理函数
EventDispatcher.on("customEvent", customEventHandle1, this, 0);
EventDispatcher.on("customEvent", customEventHandle2, this, 1);

// 触发事件
EventDispatcher.emit("customEvent", "Hello, World!");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

在这里插入图片描述

  • 添加一次性事件
    处理原理就是在on绑定事件中添加参数once,在emit触发事件并移除一次性事件处理函数
class EventDispatcher {
  static readonly events: { [key: string]: any[] } = {};

  /**
   * 绑定事件
   * @param {string} eventName 监听事件
   * @param {function} callback 监听函数
   * @param {object} target 监听目标
   * @param {number} priority 事件处理优先级
   * @param {boolean} once 一次性事件
   */
  static on(
    eventName: string,
    callback: Function,
    target: any,
    priority: number = 0,
    once: boolean = false
  ) {
    const objHandler: {} = { callback, target, priority, once };
    let handlerList: Array<any> = this.events[eventName];
    if (!handlerList) {
      handlerList = [];
      this.events[eventName] = handlerList;
    }
    handlerList.push(objHandler);
    handlerList.sort((a, b) => b.priority - a.priority); // 按优先级降序排序
  }

  // 移除事件
  static off(eventName: string, callback: Function, target: any) {
    const list = this.events[eventName];
    if (list) {
      for (let i = 0; i < list.length; i++) {
        const oldObj = list[i];
        if (
          oldObj.callback === callback &&
          (!target || target === oldObj.target)
        ) {
          list.splice(i, 1);
          break;
        }
      }
    }
  }

  // 触发事件
  static emit(eventName: string, ...args) {
    if (this.events[eventName]) {
      // 触发事件并移除一次性事件处理函数
      this.events[eventName] = this.events[eventName].filter((item) => {
        item.callback(...args);
        return !item.once;
      });
    }
  }

  /**
   * 销毁全部事件分发
   */
  static destroyAll(): void {
    //销毁方法1
    for (const eventName in this.events) {
      if (this.events.hasOwnProperty(eventName)) {
        this.events[eventName].length = 0;
        delete this.events[eventName];
      }
    }
    //销毁方法2 这个比较暴力
    // (this.events as any) = {};
  }
}
function customEventHandle1(message) {
  console.log("这个优先级设置是0,所以优先级靠后:", message);
}
function customEventHandle2(message) {
  console.log("这个优先级设置是1,所以优先级靠前:", message);
}
// 绑定事件处理函数
EventDispatcher.on("customEvent", customEventHandle1, this, 0, true);
EventDispatcher.on("customEvent", customEventHandle2, this, 1, false);

// 触发事件
EventDispatcher.emit("customEvent", "Hello, World!");
// 再次触发事件,一次性事件处理函数将不会被调用 customEventHandle1
EventDispatcher.emit("customEvent", "Hello again!");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

在这里插入图片描述

  • 添加阻止事件冒泡
class EventDispatcher {
  static readonly events: { [key: string]: any[] } = {};

  /**
   * 绑定事件
   * @param {string} eventName 监听事件
   * @param {function} callback 监听函数
   * @param {object} target 监听目标
   * @param {number} priority 事件处理优先级
   * @param {boolean} once 一次性事件
   * @param {boolean} stopped 阻止事件冒泡
   */
  static on(
    eventName: string,
    callback: Function,
    target: any,
    priority: number = 0,
    once: boolean = false,
    stopped: boolean = false
  ) {
    const objHandler: {} = { callback, target, priority, once, stopped };
    let handlerList: Array<any> = this.events[eventName];
    if (!handlerList) {
      handlerList = [];
      this.events[eventName] = handlerList;
    }
    handlerList.push(objHandler);
    handlerList.sort((a, b) => b.priority - a.priority); // 按优先级降序排序
  }

  // 移除事件
  static off(eventName: string, callback: Function, target: any) {
    const list = this.events[eventName];
    if (list) {
      for (let i = 0; i < list.length; i++) {
        const oldObj = list[i];
        if (
          oldObj.callback === callback &&
          (!target || target === oldObj.target)
        ) {
          list.splice(i, 1);
          break;
        }
      }
    }
  }

  // 触发事件
  static emit(eventName: string, ...args) {
    if (this.events[eventName]) {
      let stopFlag: boolean = false;
      // 触发事件并移除一次性事件处理函数
      this.events[eventName] = this.events[eventName].filter((item) => {
        if (stopFlag) {
          return true;
        }
        item.callback(...args);
        if (item.stopped) {
          stopFlag = true;
        }
        return !item.once;
      });
    }
  }

  /**
   * 销毁全部事件分发
   */
  static destroyAll(): void {
    //销毁方法1
    for (const eventName in this.events) {
      if (this.events.hasOwnProperty(eventName)) {
        this.events[eventName].length = 0;
        delete this.events[eventName];
      }
    }
    //销毁方法2 这个比较暴力
    // (this.events as any) = {};
  }
}
function buttonEventHandle1(message) {
  console.log("这个优先级设置是0,所以优先级靠后:", message);
}
function buttonEventHandle2(message) {
  console.log("这个优先级设置是1,所以优先级靠前:", message);
}
// 绑定事件处理函数
EventDispatcher.on("buttonEvent", buttonEventHandle1, this, 0, false, false); // stopped false不阻止
EventDispatcher.on("buttonEvent", buttonEventHandle2, this, 1, false, true); // stopped true阻止事件冒泡  因为这里设置了所以后面的buttonEventHandle1方法将不会调用
const testArgs = { message: "Hello, World!" };
// 触发事件
EventDispatcher.emit("buttonEvent", testArgs);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/449129
推荐阅读
相关标签
  

闽ICP备14008679号