【设计模式】前端必懂EventEmitter
本文說一下 EventEmitter,比較簡單,可以直接看代碼。
發布 + 訂閱
DOM 的事件機制就是發布訂閱模式最常見的實現,這大概是前端最常用的編程模型了,監聽某事件,當該事件發生時,監聽該事件的監聽函數被調用。
發布訂閱模式,阮一峰在《Javascript 異步編程的 4 種方法》,中:
我們假定,存在一個"信號中心",某個任務執行完成,就向信號中心"發布"(publish)一個信號,其他任務可以向信號中心"訂閱"(subscribe)這個信號,從而知道什么時候自己可以開始執行。這就叫做"發布/訂閱模式"(publish-subscribe pattern),又稱"觀察者模式"(observer pattern)。
感興趣的可以去看看,下圖是我平時在用的一個實現。(重點看)
class EventEmitter {constructor() {this._events = Object.create(null);}on(type, handler) {(this._events[type] || (this._events[type] = [])).push(handler);}off(type, handler) {if (this._events[type]) {this._events[type].splice(this._events[type].indexOf(handler) >>> 0, 1);}}once(type, handler) {let fired = false;function magic() {this.off(type, magic);if (!fired) {fired = true;handler.apply(this, arguments);}}this.on(type, magic);}emit(type) {let payload = [].slice.call(arguments, 1);let array = this._events[type] || [];for (let i = 0; i < array.length; i++) {let handler = this._events[type][i];handler.apply(this, payload);}} }export default EventEmitter; 復制代碼Vue 中非父子組件組件通信
在 Vue 中不同組件之間通訊,有一種解決方案叫Event Bus,這其實就是發布訂閱模式的實現,非常簡單好用。
// bus.js export default new Vue();// 使用$on監聽 import Bus from '../bus.js';export default {created(){Bus.$on('fulfilled',text=>{this.status = 'fulfilled'})} }// 使用$emit觸發事件 fetch('/data.json).then((res)=>{return res.json() }).then(()=>{Bus.$emit('fulfilled','已成功') }).catch(()=>{Bus.$emit('resolved','出錯'); }) 復制代碼Vue 事件相關接口:
emit,off。
使用 Event Bus 進行跨組件消息傳遞很棒,但是,當事件非常多的時候,Event Bus 上的事件就會難以維護,這與使用全局變量一樣一個道理。變量能局部的,就盡量不要放到全局,同樣 Event Bus 上的事件也是越少越好。
觀察者模式
簡單創建一個能夠添加、刪除和提醒觀察者的目標。
class Subject {constructor() {this.observer_list = [];}add_observer(obj) {this.observer_list.push(obj);}remove_observer(obj) {for (let i = 0; i < this.observer_list.length; i++) {if (this.observer_list[i] === obj) {this.observer_list.splice(i, 1);}}}notify() {let args = Array.prototype.slice.call(arguments, 0);for (let i = 0; i < this.observer_list.length; i++) {this.observer_list[i].update(args);}} } 復制代碼代碼會說話,我就不解釋了,實在是沒什么好解釋的,如果一定要說點什么:我真有點不好意思打原創的標。
發布訂閱模式 與 觀察者模式
有時候人們會簡單的把發布訂閱模式和觀察者模式混為一談,比如上面的一峰老師,其實兩者還是有些區別的。至少它們的英文名稱不同:Observer vs Pub-Sub。
《Learning JavaScript Design Patterns》一書這樣說:
“While the Observer pattern is useful to be aware of, quite often in the JavaScript world, we’ll find it commonly implemented using a variation known as the Publish/Subscribe pattern.” 雖然 Observer 模式非常有用,但是在 JavaScript 的世界中,它更多的以一種被稱為發布/訂閱模式的變種來實現
由上可以理解為,發布/訂閱模式是觀察者模式的一種變形,兩者區別在于,發布/訂閱模式在觀察者模式的基礎上,在目標和觀察者之間增加一個調度中心。
觀察者模式是由具體目標調度,比如當事件觸發,Subject 就會去調用觀察者的方法,所以觀察者模式的訂閱者與發布者之間是存在依賴的。
發布/訂閱模式由統一調度中心調用,因此發布者和訂閱者不需要知道對方的存在。
詳細內容,感興趣的同學可以看下面這本書:
總結
以上是生活随笔為你收集整理的【设计模式】前端必懂EventEmitter的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 聚能聊每周精选 第二十三期
- 下一篇: 浏览器是如何解析html的?