一個自定義事件封裝,WeakMap的應用

本事件封裝類特色是支持對象事件名,支持弱應用,可以確保監聽自動刪除

// 用 Symbol模擬私有變量
const event = Symbol("eventPropery");
const eventWeak = Symbol("eventProperyWeak");
const getEvent = Symbol("getEvent");
const isWeakEvent = Symbol("isWeakEvent");
/**
 * 一個公共的事件處理器 用於誇組件通信
 */
 class EventSelf {
  constructor() {
    this[event] = {};
    this[eventWeak] = new WeakMap();
  }

  [isWeakEvent](eventName) {
    return eventName !== null && typeof eventName === "object";
  }

  [getEvent](eventName) {
    let funs = null;
    if (this[isWeakEvent](eventName)) {
      funs = this[eventWeak].get(eventName);
    } else {
      funs = this[event][eventName];
    }
    return funs;
  }

  /**
   * 監聽事件
   * @param {*} eventName  任意值
   * @param {*} fun 必須是一個函數
   * @returns 返回一個解除事件監聽函數
   */
  on(eventName, fun) {
    let voidFun = () => {};
    if (!fun || !(fun instanceof Function)) {
      return voidFun;
    }
    if (!eventName) {
      return voidFun;
    }

    const funs = this[getEvent](eventName);

    if (!funs) {
      if (this[isWeakEvent](eventName)) {
        this[eventWeak].set(eventName, [fun]);
      } else {
        this[event][eventName] = [fun];
      }
    } else {
      funs.push(fun);
    }

    return () => {
      this.unBind(eventName, fun);
    };
  }
  /**
   * 觸發事件
   * @param {*} eventName  任意值
   * @param {*} val 任意值
   * @returns
   */
  emit(eventName, val) {
    if (!eventName) {
      return;
    }
    const funs = this[getEvent](eventName);

    if (!funs || funs.length === 0) {
      return;
    }

    for (const fun of funs) {
      if (fun && fun instanceof Function) {
        fun(val);
      }
    }
  }

  /**
   * 解除事件監聽
   * @param {*} eventName  任意值
   * @param {*} fun 必須是函數
   * @returns
   */
  unBind(eventName, fun) {
    const funs = this[getEvent](eventName);
    if (!funs || funs.length === 0) {
      return;
    }
    if (!(fun instanceof Function)) {
      return;
    }
    console.log('解綁函數開始執行',eventName,funs)
    const index = funs.findIndex((item) => item === fun);
    if (index !== -1) {
      funs.splice(index, 1);
    }

    console.log('解綁函數被執行',eventName,funs)
  }
}
export const gEventName = { login: "login" };
export const gEvent = new EventSelf();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章