近日沉迷搬磚(偷懶),都沒什麼時間更新文章了,磚搬的差很少了趕忙回來寫點小玩意~數組
依舊是背景介紹,咱們在網購的時候都填過地址吧,通常點擊編輯地址的時候都會跳到新的頁面,那麼問題來了,咱們編輯好提交以後,怎麼把數據給回上一個頁面呢?app
若是咱們遇到上面的情景會怎麼解決呢?方案倒很多,storage、狀態管理甚至暫存到全局。今天我想介紹的方案是EventBus,也就是咱們常說的事件總線,也能夠認爲是發佈/訂閱模式,廢話很少說,直接進入正題。函數
引入事件總線以後,在下單頁跳轉至地址編輯頁以前,咱們能夠訂閱一個事件例如:訂閱一個key爲"address"的事件,並規定事件觸發後該執行的函數,好比將獲取到的信息展現出來。this
在地址編輯頁完成編輯後,咱們會發佈一個key爲"address"的事件,並傳遞一些參數(例如此處應傳遞地址信息)。事件發佈後,會觸發訂閱通道中key爲"address"的事件回調。這樣就完成了咱們須要的數據傳遞並展現。3d
首先咱們看張示意圖,對EventBus有個更直觀的瞭解。cdn
不難發現,咱們完成一個簡易的EventBus其實只需這麼3個方法 -- on/emit/off對象
首先構造一個EventBus函數,而後給它賦予on方法。該方法可傳入三個值,key/cb/isKeep分別表明訂閱的鍵值、事件回調以及是否持久化訂閱。blog
實際狀況中,咱們不少時候的事件訂閱都是一次性動做,因此咱們的訂閱行爲默認是一次性的而且isKeep也不做爲必備參數。token
可是key則不同,若是沒有key的傳入這個方法是徹底沒有意義的,因此咱們將key值設爲必備的參數。得到key後,首先會在events對象中查看是否已存在,若是沒有則爲這個key新增一個屬性並賦予空組數,最後把事件回調以及是否持久化做爲對象傳入數組中。事件
若是咱們不想再訂閱某個事件,咱們就須要一個取消訂閱的方法,由於咱們一個訂閱事件是能夠觸發多個回調的,因此咱們取消訂閱有兩種模式,一種是取消某個回調,一種是取消整個事件訂閱。
這裏咱們可傳入兩個值,一個是key一個是cb,若是沒有傳入cb則表明取消整個事件訂閱。
取消整個事件訂閱好辦,直接將this.events內的對應key的屬性delete便可。若是須要刪除指定key的某個回調則須要把目標回調函數引用也傳入off方法中,找到相應對象刪除。
看到這裏,你們可能會想,若是我傳的是個匿名函數不是就無法取消了?恭喜你,答對了。因此咱們在設置回調函數的時候儘可能不要使用匿名函數。(若是咱們確實須要取消應該咋辦?在拓展中咱們會展開討論一下)
最後是事件發佈,發佈的重點在於參數的傳遞以及一次性訂閱的取消。咱們經過函數內置的arguments屬性將須要傳入觸發事件的參數取出來,而後經過apply方法傳入函數中。
對於不須要keep的訂閱,咱們則須要在handler觸發後調用自身的off方法將其刪除便可。
乍一看,兩種模式十分類似,都有所謂的訂閱與發佈動做,但有一個很大的不一樣:調度方式。
發佈/訂閱模式有一個調度中心的概念,也就是咱們這裏所說的事件總線,全部的事件調度都是在這裏面進行的;而觀察者模式則是由被觀察對象主動調度,沒有事件總線的概念。相比之下發布/訂閱模式更加解耦,發佈、訂閱者徹底沒有依賴。
① 若是是一次性訂閱則能夠直接根據引用進行訂閱取消。
② 若是不是一次性訂閱,可是咱們又想取消則能夠參照setTimeout的作法,咱們在訂閱事件的時候隨機生成一個token,並加入訂閱對象中,最後做爲on的返回值,暴露出來。取消訂閱也是意義,就和咱們clearTimeout同樣,將token傳入off方法中,達到取消的目的。