在經常使用的MVVM框架好比vue,組件間通訊可能會有如下三種狀況:vue
1. 父子通訊:經過props 2. 非父子組件組件用eventBus通訊 3. 若是項目很大,數據須要共享到多個組件(跨組件通訊,改同一個數據等),用vuex管理
那麼文中的eventBus是怎麼實現的呢,就是根據發佈訂閱模式。發佈訂閱模式應用普遍,js事件就是一個經典的發佈訂閱模式。看個例子addEventListenerjava
EventTarget.addEventListener() 方法將指定的監聽器註冊到 EventTarget 上,當該對象觸發指定的事件時,指定的回調函數就會被執行,事件目標能夠是一個文檔上的元素 Document 自己。
target.addEventListener(type, listener, options); //type 表示事件類型(eg:click) //listener 回調函數,當監聽的事件類型觸發時,執行listener函數 //options 冒泡仍是捕獲等參數
原生js中,咱們經過addEventListener註冊事件(訂閱),好比鼠標點擊,傳入回調函數(在註冊的事件觸發時要執行的函數),那麼鼠標點擊時(發佈),傳入的回調函數就會執行。除了原生js事件。vuex
那一個簡單的發佈訂閱模式怎麼實現呢?定義一個EventEmitter類,它有如下幾個元素:設計模式
代碼以下:數組
class EventEmitter { constructor(){ //單例模式 this._events = this._events || new Map(); } //發佈(觸發事件) emit(type, ...args){ //拿到訂閱者的回調函數 var handler = this._events.get(type); if(!handler){ return; } //發佈時,依次執行訂閱者的回調 for(var i = 0; i< handler.length; i++){ handler[i].apply(this, args); } } //訂閱(監聽事件) addListener(type, func){ var handler = this._events.get(type); //若是尚未同類型的訂閱,新建立一個 if(!handler){ this._events.set(type, [func]); return; } //把回調函數塞入數組 handler.push(func); } //移除 removeListener(type, func){ var handler = this._events.get(type); if(!handler){ return; } for(var i = handler.length; i>0; i--){ //找到本身要移除的函數,匿名函數不能移除 if(handler[i] == func){ handler.splice(i, 1); } } } }
該實現只是探究原理,異常處理之類的都沒作。想了解單例模式能夠看:《javaScript設計模式與開發實踐》(我還沒看完emmm)app
參考:框架
[eventBus實現][2]