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!");

在这里插入图片描述

如果涉及到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!");

有没有发现当使用了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!");

在这里插入图片描述

  • 添加一次性事件
    处理原理就是在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!");

在这里插入图片描述

  • 添加阻止事件冒泡
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);

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值