溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript如何實現(xiàn)事件總線

發(fā)布時間:2022-05-30 10:32:17 來源:億速云 閱讀:156 作者:zzz 欄目:開發(fā)技術(shù)

這篇文章主要講解了“JavaScript如何實現(xiàn)事件總線”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“JavaScript如何實現(xiàn)事件總線”吧!

    介紹

    Event Bus 事件總線,通常作為多個模塊間的通信機(jī)制,相當(dāng)于一個事件管理中心,一個模塊發(fā)送消息,其它模塊接受消息,就達(dá)到了通信的作用。

    比如,Vue 組件間的數(shù)據(jù)傳遞可以使用一個 Event Bus 來通信,也可以用作微內(nèi)核插件系統(tǒng)中的插件和核心通信。

    原理

    Event Bus 本質(zhì)上是采用了發(fā)布-訂閱的設(shè)計模式,比如多個模塊 A、BC 訂閱了一個事件 EventX,然后某一個模塊 X 在事件總線發(fā)布了這個事件,那么事件總線會負(fù)責(zé)通知所有訂閱者 AB、C,它們都能收到這個通知消息,同時還可以傳遞參數(shù)。

    JavaScript如何實現(xiàn)事件總線

    分析

    如何使用 JavaScript 來實現(xiàn)一個簡單版本的 Event Bus

    • 首先構(gòu)造一個 EventBus 類,初始化一個空對象用于存放所有的事件

    • 在接受訂閱時,將事件名稱作為 key 值,將需要在接受發(fā)布消息后執(zhí)行的回調(diào)函數(shù)作為 value 值,由于一個事件可能有多個訂閱者,所以這里的回調(diào)函數(shù)要存儲成列表

    • 在發(fā)布事件消息時,從事件列表里取得指定的事件名稱對應(yīng)的所有回調(diào)函數(shù),依次觸發(fā)執(zhí)行即可

    以下是代碼詳細(xì)實現(xiàn),可以復(fù)制到谷歌瀏覽器控制臺直接運(yùn)行檢測效果。

    代碼

    class EventBus {
      constructor() {
        // 初始化事件列表
        this.eventObject = {};
      }
      // 發(fā)布事件
      publish(eventName) {
        // 取出當(dāng)前事件所有的回調(diào)函數(shù)
        const callbackList = this.eventObject[eventName];
    
        if (!callbackList) return console.warn(eventName + " not found!");
    
        // 執(zhí)行每一個回調(diào)函數(shù)
        for (let callback of callbackList) {
          callback();
        }
      }
      // 訂閱事件
      subscribe(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          this.eventObject[eventName] = [];
        }
    
        // 存儲訂閱者的回調(diào)函數(shù)
        this.eventObject[eventName].push(callback);
      }
    }
    
    // 測試
    const eventBus = new EventBus();
    
    // 訂閱事件eventX
    eventBus.subscribe("eventX", () => {
      console.log("模塊A");
    });
    eventBus.subscribe("eventX", () => {
      console.log("模塊B");
    });
    eventBus.subscribe("eventX", () => {
      console.log("模塊C");
    });
    
    // 發(fā)布事件eventX
    eventBus.publish("eventX");
    
    // 輸出
    > 模塊A
    > 模塊B
    > 模塊C

    上面我們實現(xiàn)了最基礎(chǔ)的發(fā)布和訂閱功能,實際應(yīng)用中,還可能有更進(jìn)階的需求。

    進(jìn)階

    1. 如何在發(fā)送消息時傳遞參數(shù)

    發(fā)布者傳入一個參數(shù)到 EventBus 中,在 callback 回調(diào)函數(shù)執(zhí)行的時候接著傳出參數(shù),這樣每一個訂閱者就可以收到參數(shù)了。

    代碼

    class EventBus {
      constructor() {
        // 初始化事件列表
        this.eventObject = {};
      }
      // 發(fā)布事件
      publish(eventName, ...args) {
        // 取出當(dāng)前事件所有的回調(diào)函數(shù)
        const callbackList = this.eventObject[eventName];
    
        if (!callbackList) return console.warn(eventName + " not found!");
    
        // 執(zhí)行每一個回調(diào)函數(shù)
        for (let callback of callbackList) {
          // 執(zhí)行時傳入?yún)?shù)
          callback(...args);
        }
      }
      // 訂閱事件
      subscribe(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          this.eventObject[eventName] = [];
        }
    
        // 存儲訂閱者的回調(diào)函數(shù)
        this.eventObject[eventName].push(callback);
      }
    }
    
    // 測試
    const eventBus = new EventBus();
    
    // 訂閱事件eventX
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊A", obj, num);
    });
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊B", obj, num);
    });
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊C", obj, num);
    });
    
    // 發(fā)布事件eventX
    eventBus.publish("eventX", { msg: "EventX published!" }, 1);
    
    
    // 輸出
    > 模塊A {msg: 'EventX published!'} 1
    > 模塊B {msg: 'EventX published!'} 1
    > 模塊C {msg: 'EventX published!'} 1

    2. 訂閱后如何取消訂閱

    有時候訂閱者只想在某一個時間段訂閱消息,這就涉及帶取消訂閱功能。我們將對代碼進(jìn)行改造。

    首先,要實現(xiàn)指定訂閱者取消訂閱,每一次訂閱事件時,都生成唯一一個取消訂閱的函數(shù),用戶直接調(diào)用這個函數(shù),我們就把當(dāng)前訂閱的回調(diào)函數(shù)刪除。

    // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
    const unSubscribe = () => {
      // 清除這個訂閱者的回調(diào)函數(shù)
      delete this.eventObject[eventName][id];
    };

    其次,訂閱的回調(diào)函數(shù)列表使換成對象結(jié)構(gòu)存儲,為每一個回調(diào)函數(shù)設(shè)定一個唯一 id, 注銷回調(diào)函數(shù)的時候可以提高刪除的效率,如果還是使用數(shù)組的話需要使用 split 刪除,效率不如對象的 delete

    代碼

    class EventBus {
      constructor() {
        // 初始化事件列表
        this.eventObject = {};
        // 回調(diào)函數(shù)列表的id
        this.callbackId = 0;
      }
      // 發(fā)布事件
      publish(eventName, ...args) {
        // 取出當(dāng)前事件所有的回調(diào)函數(shù)
        const callbackObject = this.eventObject[eventName];
    
        if (!callbackObject) return console.warn(eventName + " not found!");
    
        // 執(zhí)行每一個回調(diào)函數(shù)
        for (let id in callbackObject) {
          // 執(zhí)行時傳入?yún)?shù)
          callbackObject[id](...args);
        }
      }
      // 訂閱事件
      subscribe(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this.eventObject[eventName] = {};
        }
    
        const id = this.callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this.eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this.eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this.eventObject[eventName]).length === 0) {
            delete this.eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    }
    
    // 測試
    const eventBus = new EventBus();
    
    // 訂閱事件eventX
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊A", obj, num);
    });
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊B", obj, num);
    });
    const subscriberC = eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊C", obj, num);
    });
    
    // 發(fā)布事件eventX
    eventBus.publish("eventX", { msg: "EventX published!" }, 1);
    
    // 模塊C取消訂閱
    subscriberC.unSubscribe();
    
    // 再次發(fā)布事件eventX,模塊C不會再收到消息了
    eventBus.publish("eventX", { msg: "EventX published again!" }, 2);
    
    // 輸出
    > 模塊A {msg: 'EventX published!'} 1
    > 模塊B {msg: 'EventX published!'} 1
    > 模塊C {msg: 'EventX published!'} 1
    > 模塊A {msg: 'EventX published again!'} 2
    > 模塊B {msg: 'EventX published again!'} 2

    3. 如何只訂閱一次

    如果一個事件只發(fā)生一次,通常也只需要訂閱一次,收到消息后就不用再接受消息。

    首先,我們提供一個 subscribeOnce 的接口,內(nèi)部實現(xiàn)幾乎和 subscribe 一樣,只有一個地方有區(qū)別,在 callbackId 前面的加一個字符 d,用來標(biāo)示這是一個需要刪除的訂閱。

    // 標(biāo)示為只訂閱一次的回調(diào)函數(shù)
    const id = "d" + this.callbackId++;

    然后,在執(zhí)行回調(diào)函數(shù)后判斷當(dāng)前回調(diào)函數(shù)的 id 有沒有標(biāo)示,決定我們是否需要刪除這個回調(diào)函數(shù)。

    // 只訂閱一次的回調(diào)函數(shù)需要刪除
    if (id[0] === "d") {
      delete callbackObject[id];
    }

    代碼

    class EventBus {
      constructor() {
        // 初始化事件列表
        this.eventObject = {};
        // 回調(diào)函數(shù)列表的id
        this.callbackId = 0;
      }
      // 發(fā)布事件
      publish(eventName, ...args) {
        // 取出當(dāng)前事件所有的回調(diào)函數(shù)
        const callbackObject = this.eventObject[eventName];
    
        if (!callbackObject) return console.warn(eventName + " not found!");
    
        // 執(zhí)行每一個回調(diào)函數(shù)
        for (let id in callbackObject) {
          // 執(zhí)行時傳入?yún)?shù)
          callbackObject[id](...args);
    
          // 只訂閱一次的回調(diào)函數(shù)需要刪除
          if (id[0] === "d") {
            delete callbackObject[id];
          }
        }
      }
      // 訂閱事件
      subscribe(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this.eventObject[eventName] = {};
        }
    
        const id = this.callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this.eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this.eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this.eventObject[eventName]).length === 0) {
            delete this.eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    
      // 只訂閱一次
      subscribeOnce(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this.eventObject[eventName] = {};
        }
    
        // 標(biāo)示為只訂閱一次的回調(diào)函數(shù)
        const id = "d" + this.callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this.eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this.eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this.eventObject[eventName]).length === 0) {
            delete this.eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    }
    
    // 測試
    const eventBus = new EventBus();
    
    // 訂閱事件eventX
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊A", obj, num);
    });
    eventBus.subscribeOnce("eventX", (obj, num) => {
      console.log("模塊B", obj, num);
    });
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊C", obj, num);
    });
    
    // 發(fā)布事件eventX
    eventBus.publish("eventX", { msg: "EventX published!" }, 1);
    
    // 再次發(fā)布事件eventX,模塊B只訂閱了一次,不會再收到消息了
    eventBus.publish("eventX", { msg: "EventX published again!" }, 2);
    
    // 輸出
    > 模塊A {msg: 'EventX published!'} 1
    > 模塊C {msg: 'EventX published!'} 1
    > 模塊B {msg: 'EventX published!'} 1
    > 模塊A {msg: 'EventX published again!'} 2
    > 模塊C {msg: 'EventX published again!'} 2

    4. 如何清除某個事件或者所有事件

    我們還希望通過一個 clear 的操作來將指定事件的所有訂閱清除掉,這個通常在一些組件或者模塊卸載的時候用到。

      // 清除事件
      clear(eventName) {
        // 未提供事件名稱,默認(rèn)清除所有事件
        if (!eventName) {
          this.eventObject = {};
          return;
        }
    
        // 清除指定事件
        delete this.eventObject[eventName];
      }

    和取消訂閱的邏輯相似,只不過這里統(tǒng)一處理了。

    代碼

    class EventBus {
      constructor() {
        // 初始化事件列表
        this.eventObject = {};
        // 回調(diào)函數(shù)列表的id
        this.callbackId = 0;
      }
      // 發(fā)布事件
      publish(eventName, ...args) {
        // 取出當(dāng)前事件所有的回調(diào)函數(shù)
        const callbackObject = this.eventObject[eventName];
    
        if (!callbackObject) return console.warn(eventName + " not found!");
    
        // 執(zhí)行每一個回調(diào)函數(shù)
        for (let id in callbackObject) {
          // 執(zhí)行時傳入?yún)?shù)
          callbackObject[id](...args);
    
          // 只訂閱一次的回調(diào)函數(shù)需要刪除
          if (id[0] === "d") {
            delete callbackObject[id];
          }
        }
      }
      // 訂閱事件
      subscribe(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this.eventObject[eventName] = {};
        }
    
        const id = this.callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this.eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this.eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this.eventObject[eventName]).length === 0) {
            delete this.eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    
      // 只訂閱一次
      subscribeOnce(eventName, callback) {
        // 初始化這個事件
        if (!this.eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this.eventObject[eventName] = {};
        }
    
        // 標(biāo)示為只訂閱一次的回調(diào)函數(shù)
        const id = "d" + this.callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this.eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this.eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this.eventObject[eventName]).length === 0) {
            delete this.eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    
      // 清除事件
      clear(eventName) {
        // 未提供事件名稱,默認(rèn)清除所有事件
        if (!eventName) {
          this.eventObject = {};
          return;
        }
    
        // 清除指定事件
        delete this.eventObject[eventName];
      }
    }
    
    // 測試
    const eventBus = new EventBus();
    
    // 訂閱事件eventX
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊A", obj, num);
    });
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊B", obj, num);
    });
    eventBus.subscribe("eventX", (obj, num) => {
      console.log("模塊C", obj, num);
    });
    
    // 發(fā)布事件eventX
    eventBus.publish("eventX", { msg: "EventX published!" }, 1);
    
    // 清除
    eventBus.clear("eventX");
    
    // 再次發(fā)布事件eventX,由于已經(jīng)清除,所有模塊都不會再收到消息了
    eventBus.publish("eventX", { msg: "EventX published again!" }, 2);
    
    // 輸出
    > 模塊A {msg: 'EventX published!'} 1
    > 模塊B {msg: 'EventX published!'} 1
    > 模塊C {msg: 'EventX published!'} 1
    > eventX not found!

    5. TypeScript 版本

    鑒于現(xiàn)在 TypeScript 已經(jīng)被大規(guī)模采用,尤其是大型前端項目,我們簡要的改造為一個 TypeScript 版本

    可以復(fù)制以下代碼到 TypeScript Playground 體驗運(yùn)行效果

    代碼

    interface ICallbackList {
      [id: string]: Function;
    }
    
    interface IEventObject {
      [eventName: string]: ICallbackList;
    }
    
    interface ISubscribe {
      unSubscribe: () => void;
    }
    
    interface IEventBus {
      publish<T extends any[]>(eventName: string, ...args: T): void;
      subscribe(eventName: string, callback: Function): ISubscribe;
      subscribeOnce(eventName: string, callback: Function): ISubscribe;
      clear(eventName: string): void;
    }
    
    class EventBus implements IEventBus {
      private _eventObject: IEventObject;
      private _callbackId: number;
      constructor() {
        // 初始化事件列表
        this._eventObject = {};
        // 回調(diào)函數(shù)列表的id
        this._callbackId = 0;
      }
      // 發(fā)布事件
      publish<T extends any[]>(eventName: string, ...args: T): void {
        // 取出當(dāng)前事件所有的回調(diào)函數(shù)
        const callbackObject = this._eventObject[eventName];
    
        if (!callbackObject) return console.warn(eventName + " not found!");
    
        // 執(zhí)行每一個回調(diào)函數(shù)
        for (let id in callbackObject) {
          // 執(zhí)行時傳入?yún)?shù)
          callbackObject[id](...args);
    
          // 只訂閱一次的回調(diào)函數(shù)需要刪除
          if (id[0] === "d") {
            delete callbackObject[id];
          }
        }
      }
      // 訂閱事件
      subscribe(eventName: string, callback: Function): ISubscribe {
        // 初始化這個事件
        if (!this._eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this._eventObject[eventName] = {};
        }
    
        const id = this._callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this._eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this._eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this._eventObject[eventName]).length === 0) {
            delete this._eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    
      // 只訂閱一次
      subscribeOnce(eventName: string, callback: Function): ISubscribe {
        // 初始化這個事件
        if (!this._eventObject[eventName]) {
          // 使用對象存儲,注銷回調(diào)函數(shù)的時候提高刪除的效率
          this._eventObject[eventName] = {};
        }
    
        // 標(biāo)示為只訂閱一次的回調(diào)函數(shù)
        const id = "d" + this._callbackId++;
    
        // 存儲訂閱者的回調(diào)函數(shù)
        // callbackId使用后需要自增,供下一個回調(diào)函數(shù)使用
        this._eventObject[eventName][id] = callback;
    
        // 每一次訂閱事件,都生成唯一一個取消訂閱的函數(shù)
        const unSubscribe = () => {
          // 清除這個訂閱者的回調(diào)函數(shù)
          delete this._eventObject[eventName][id];
    
          // 如果這個事件沒有訂閱者了,也把整個事件對象清除
          if (Object.keys(this._eventObject[eventName]).length === 0) {
            delete this._eventObject[eventName];
          }
        };
    
        return { unSubscribe };
      }
    
      // 清除事件
      clear(eventName: string): void {
        // 未提供事件名稱,默認(rèn)清除所有事件
        if (!eventName) {
          this._eventObject = {};
          return;
        }
    
        // 清除指定事件
        delete this._eventObject[eventName];
      }
    }
    
    // 測試
    interface IObj {
      msg: string;
    }
    
    type PublishType = [IObj, number];
    
    const eventBus = new EventBus();
    
    // 訂閱事件eventX
    eventBus.subscribe("eventX", (obj: IObj, num: number, s: string) => {
      console.log("模塊A", obj, num);
    });
    eventBus.subscribe("eventX", (obj: IObj, num: number) => {
      console.log("模塊B", obj, num);
    });
    eventBus.subscribe("eventX", (obj: IObj, num: number) => {
      console.log("模塊C", obj, num);
    });
    
    // 發(fā)布事件eventX
    eventBus.publish("eventX", { msg: "EventX published!" }, 1);
    
    // 清除
    eventBus.clear("eventX");
    
    // 再次發(fā)布事件eventX,由于已經(jīng)清除,所有模塊都不會再收到消息了
    eventBus.publish<PublishType>("eventX", { msg: "EventX published again!" }, 2);
    
    // 輸出
    [LOG]: "模塊A",  {
      "msg": "EventX published!"
    },  1
    [LOG]: "模塊B",  {
      "msg": "EventX published!"
    },  1
    [LOG]: "模塊C",  {
      "msg": "EventX published!"
    },  1
    [WRN]: "eventX not found!"

    6. 單例模式

    在實際使用過程中,往往只需要一個事件總線就能滿足需求,這里有兩種情況,保持在上層實例中單例和全局單例。

    1.保持在上層實例中單例

    將事件總線引入到上層實例使用,只需要保證在一個上層實例中只有一個 EventBus,如果上層實例有多個,意味著有多個事件總線,但是每個上層實例管控自己的事件總線。

    首先在上層實例中建立一個變量用來存儲事件總線,只在第一次使用時初始化,后續(xù)其他模塊使用事件總線時直接取得這個事件總線實例。

    代碼

    // 上層實例
    class LWebApp {
      private _eventBus?: EventBus;
    
      constructor() {}
    
      public getEventBus() {
        // 第一次初始化
        if (this._eventBus == undefined) {
          this._eventBus = new EventBus();
        }
    
        // 后續(xù)每次直接取唯一一個實例,保持在LWebApp實例中單例
        return this._eventBus;
      }
    }
    
    // 使用
    const eventBus = new LWebApp().getEventBus();

    2.全局單例

    有時候我們希望不管哪一個模塊想使用我們的事件總線,我們都想這些模塊使用的是同一個實例,這就是全局單例,這種設(shè)計能更容易統(tǒng)一管理事件。

    寫法同上面的類似,區(qū)別是要把 _eventBus 和 getEventBus 轉(zhuǎn)為靜態(tài)屬性。使用時無需實例化 EventBusTool 工具類,直接使用靜態(tài)方法就行了。

    代碼

    // 上層實例
    class EventBusTool {
      private static _eventBus?: EventBus;
    
      constructor() {}
    
      public static getEventBus(): EventBus {
        // 第一次初始化
        if (this._eventBus == undefined) {
          this._eventBus = new EventBus();
        }
    
        // 后續(xù)每次直接取唯一一個實例,保持全局單例
        return this._eventBus;
      }
    }
    
    // 使用
    const eventBus = EventBusTool.getEventBus();

    感謝各位的閱讀,以上就是“JavaScript如何實現(xiàn)事件總線”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對JavaScript如何實現(xiàn)事件總線這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI