這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰。前端
專門爲8月徵文活動而創建的系列,收集整理前端一些有意思或者咱們不重視的內容,多是部分掘友不知道的。node
無處不在的訂閱發佈模式,也是常備手寫系列,可見其地位。web
其實,在瀏覽器端,3行代碼,沒錯3行代碼,你就能夠擁有一個具有訂閱,取消訂閱,發佈,並具有once能力的訂閱發佈中心。瀏覽器
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" })
複製代碼
是否是有點小驚喜。oop
window是表象,根源是 EventTarget。post
其一共三個方法,也正是這三個方法,讓其自身是一個訂閱發佈中心:測試
EventTarget.addEventListener()
在EventTarget上註冊特定事件類型的事件處理程序。ui
EventTarget.removeEventListener()
EventTarget中刪除事件偵聽器。this
EventTarget.dispatchEvent()
將事件分派到此EventTarget。
Window的繼承關係:
Document的繼承關係:
Element的繼承關係:
因此document和window對象均是一個訂閱發佈中心。
更重要的是咱們經常使用的div, span, input等等nodeType爲1的元素節點,也通通是一個訂閱發佈中心。
假如你連nodeType也不清楚,不要緊,請參見Node.nodeType。
到這裏,我不生氣,真的不生氣, 特定場景解決特定問題就完畢了。 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" })
複製代碼
完美,名字好看了,使用方便了,也支持多實例了。
是否是很簡單,其實不用第三方庫,你也能夠擁有訂閱發佈中心,就這麼簡單。
要是都看到這了,都不點個贊,那就是你的不對了。