【SSD系列】傻傻的,3行代碼一個訂閱發佈中心,不會不知道吧 |8月更文挑戰

這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰前端

關於[SSD系列]

專門爲8月徵文活動而創建的系列,收集整理前端一些有意思或者咱們不重視的內容,多是部分掘友不知道的。node

前言

無處不在的訂閱發佈模式,也是常備手寫系列,可見其地位。web

其實,在瀏覽器端,3行代碼,沒錯3行代碼,你就能夠擁有一個具有訂閱,取消訂閱,發佈,並具有once能力的訂閱發佈中心。瀏覽器

4行代碼的訂閱發佈中心

訂閱發佈中心代碼

window._on = window.addEventListener;
window._off = window.removeEventListener;
window._emit = (type, data) => window.dispatchEvent(new CustomEvent(type, { detail: data }));;
window._once = (type, callback) => window.addEventListener(type, callback, { once: true, capture: true });
複製代碼

標題是3行也是能夠的,把1,2行合併一下:markdown

(window._on = window.addEventListener, window._off = window.removeEventListener);
複製代碼

測試代碼

function onEventX(ev) {
    console.log("event-x 收到數據:", ev.detail);
}
​
// 訂閱
window._on("event-x", onEventX);
window._once("event-once", ev => console.log("event-once 收到數據:", ev.detail));
​
// once
window._emit("event-once", { uid: -100, message: "you love me" });
window._emit("event-once", { uid: -100, message: "you love me" });
// 訂閱和取消訂閱
window._emit("event-x", { uid: 100, message: "i love you" })
window._off("event-x", onEventX);
window._emit("event-x", { uid: 100, message: "i love you" })
複製代碼

輸出結果

image-20210802171736958.png

是否是有點小驚喜。oop

原理淺析

window是表象,根源是 EventTargetpost

其一共三個方法,也正是這三個方法,讓其自身是一個訂閱發佈中心:測試

Window的繼承關係:

image-20210802173153270.png

Document的繼承關係:

image.png

Element的繼承關係:

image.png

因此document和window對象均是一個訂閱發佈中心。

更重要的是咱們經常使用的div, span, input等等nodeType爲1的元素節點,也通通是一個訂閱發佈中心。

假如你連nodeType也不清楚,不要緊,請參見Node.nodeType

當前版本的問題

  1. 不能多實例化啊
  2. 掛載window上太醜了
  3. 不能多參數啊
    答:要那麼多參數幹嗎
  4. 參數從ev.detail上獲取
    答:還好
  5. 不能在node, web worker中使用啊
    答:node要你寫嗎, 自帶啊。 web worker嘛,確實。
  6. ........

到這裏,我不生氣,真的不生氣, 特定場景解決特定問題就完畢了。 1毛錢還想上天啊。

可是就算是1毛錢,我也但願你們得到更好的體驗,因此要改造升級。

3以及以後的別想了,咱們把1,2點進行完美升級。

升級

升級後的代碼會多一點,2倍吧,一共6行代碼

代碼

class EventEmitter extends EventTarget {
    on = this.addEventListener;
    off = this.removeEventListener;
    emit = (type, data) => this.dispatchEvent(new CustomEvent(type, { detail: data }));
    once = (type, callback) => this.on(type, callback, { once: true, capture: true });
}
複製代碼

測試代碼

       var emitter = new EventEmitter();
        function onEventX(ev) {
            console.log("event-x 收到數據:", ev.detail);
        }
​
        // 訂閱
        emitter.on("event-x", onEventX);
        emitter.once("event-once", ev => console.log("event-once 收到數據:", ev.detail));
​
        // 發佈
        emitter.emit("event-once", { uid: -100, message: "you love me" });
        emitter.emit("event-once", { uid: -100, message: "you love me" });
​
        emitter.emit("event-x", { uid: 100, message: "i love you" })
        emitter.off("event-x", onEventX);
        emitter.emit("event-x", { uid: 100, message: "i love you" })
複製代碼

完美,名字好看了,使用方便了,也支持多實例了。

結果

image.png

總結

是否是很簡單,其實不用第三方庫,你也能夠擁有訂閱發佈中心,就這麼簡單。

要是都看到這了,都不點個贊,那就是你的不對了。

相關文章
相關標籤/搜索