摘要:在觸發的時候,回調此方法,從而觸發函數。發布訂閱模式比較適合寫封裝插件,我認為拿來寫業務邏輯代碼,有點不太好用。接下來,我準備用這個模式封裝一個上傳的組件。
初始化Event對象
var initEvent = function(obj) { for(var i in event) { obj[i] = event[i]; } };
主代碼:
var event = { list: [], listen: function(key, fn) { // 確定監聽的事件容器默認是一個空數組 if(!this.list[key]) { this.list[key] = []; } // 訂閱的消息添加到緩存列表中 this.list[key].push(fn); // 鏈式調用 return this }, trigger: function(){ // 獲取trigger 函數參數的第一個參數,即key鍵 // 此時arguments 是trigger的參數類數組 var key = Array.prototype.shift.call(arguments); // 拿到對應key的監聽事件數組 var fns = this.list[key]; // 如果沒有訂閱過該消息的話,則返回 if(!fns || fns.length === 0) { return; } for(var i = 0, fn;i < fns.length; i ++) { fn = fns[i] //逐個調用key鍵所對應監聽事件數組函數 // 此時arguments 同樣也是trigger的參數類數組,只不過少了第一個參數 // 將此參數傳遞給fn函數作為形參 // this 也是fn的執行作用域 fn.apply(this, arguments); } } };
調用執行:
// 新建一個比如小紅的對象 var shoeObj = {}; // 初始化小紅對象 initEvent(shoeObj); // 小紅同時訂閱如下消息(鏈式調用) shoeObj.listen("red",function(size, price){ console.log("尺碼是:"+size); console.log("price是" +price) }).listen("block", function (size, price) { console.log("尺碼是:"+size); console.log("price是" +price) }) shoeObj.trigger("red", 40, 500); shoeObj.trigger("block",42, 300);
訂閱了消息后,我們可能會remove掉消息,所以Event對象新增一個方法:
// 略 remove : function(key, fn) { var fns = this.list[key] // 如果key對應的消息沒有訂閱過的話,則返回 if(!fns) return // 如果沒有傳入具體的回調函數,表示需要取消key對應消息的所有訂閱 if(!fn) { fns.length = 0 // 或者this.list[key] = [] // fns = [] //fns = [] 這樣寫后,實際this.list[key]中的回調數組 //依然存在,因為初始fns指向this.list[key]這個數組(數組是一個引用類型) //fns = [],代表我們將fns又指向了一個新的數組長度為空的引用數組,而這個 // 新的引用數組 和this.list[key]這個引用數組是計算機里面占用兩個不同的 // 堆棧。 }else { for(var i = 0; i < fns.length; i ++) { var _fn = fns[i] if(_fn === fn) { fns.splice(i, 1) // 刪除訂閱者的回調函數 } } } }, // 略
調用
// 小紅訂閱如下消息 同時在red上面訂閱了兩個消息 // 注意fn1 和fn2 這種寫法,比較少見,實際fn1,fn2成為了一個全局變量 // 在remove的時候,作為具體的參數傳遞 shoeObj.listen("red",fn1 = function(size, price){ console.log("尺碼是1----" +size); console.log("price是1----" +price) }).listen("red", fn2 = function(size, price){ console.log("尺碼是2----" +size); console.log("price是2----" +price) }) //remove 掉fn2 shoeObj.remove("red", fn2) // 觸發回調 此時只會回調fn1 shoeObj.trigger("red", 40, 500); //如果remove 不傳參數,就會將red中所有的監聽全部remove掉 shoeObj.remove("red") shoeObj.trigger("red", 40, 500);
結束語
發布訂閱模式是js中36中設計模式中最常見的模式,也是很重要的設計模式。其實我們在寫項目邏輯代碼的時候,無形中也運用了這個思想,最常見的是click觸發回調。比如我們定義一個方法,在定義的時候已經listen在一個對象上,或window對象上。在click觸發的時候,回調此方法,從而觸發函數。
發布訂閱模式比較適合寫封裝插件,我認為拿來寫業務邏輯代碼,有點不太好用。當然這只是我自己的觀點。
接下來,我準備用這個模式封裝一個上傳的組件。
附錄(參考文獻)
cn一篇博文
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107046.html
摘要:今天說說觀察者模式,這是一個非常常見的模式,很多事件的分發都基于此模式。這里將從一個題目來說說此模式的使用,有這樣一道題某市一家報社開張,市民訂閱報紙,嘗試使用觀察者模式解決此問題。在使用觀察者模式前,先說說普通的處理方法。 今天說說觀察者模式,這是一個非常常見的模式,很多事件的分發都基于此模式。 這里將從一個題目來說說此模式的使用,有這樣一道題: 某市一家報社開張,市民訂閱報紙,嘗試...
摘要:以下方式寫提示未定義涉及閉包作用域鏈的問題改進方式調用實例化回調函數執行成功,并執行函數,此時在回調隊列里面添加一一個函數,并將的參數傳遞出去。否則直接執行回調函數,不會由來觸發的回調函數執行。 function Promise(fn){ //需要一個成功時的回調 var self = this var callback; //一個實例的方法,用來注冊異...
摘要:接下來我們看下三類異步編程的實現。事件監聽事件發布訂閱事件監聽是一種非常常見的異步編程模式,它是一種典型的邏輯分離方式,對代碼解耦很有用處。 一、 一道面試題 前段時間面試,考察比較多的是js異步編程方面的相關知識點,如今,正好輪到自己分享技術,所以想把js異步編程學習下,做個總結。下面這個demo 概括了大多數面試過程中遇到的問題: for(var i = 0; i < 3; i++...
摘要:想繼續了解設計模式必須要先搞懂面向對象編程,否則只會讓你自己更痛苦。創建型設計模式主要有簡單工廠模式,工廠方法模式,抽象工廠模式,建造者模式,原型模式和單例模式,下面一一道來。而工廠方法模式本意是將實際創建對象的工作推遲到子類中。 接觸前端兩三個月的時候,那時候只是聽說設計模式很重要,然后我就去讀了一本設計模式的書,讀了一部分,也不知道這些設計模式到底設計出來干嘛的,然后就沒再看了。后...
摘要:或許以前認為訂閱發布模式是觀察者模式的一種別稱,但是發展至今,概念已經有了不少區別。參考文章訂閱發布模式和觀察者模式真的不一樣 首選我們需要先了解兩者的定義和實現的方式,才能更好的區分兩者的不同點。 或許以前認為訂閱發布模式是觀察者模式的一種別稱,但是發展至今,概念已經有了不少區別。 訂閱發布模式 在軟件架構中,發布-訂閱是一種消息范式,消息的發送者(稱為發布者)不會將消息直接發送給特...
閱讀 3141·2023-04-26 02:33
閱讀 3102·2023-04-25 21:33
閱讀 907·2021-09-02 09:56
閱讀 2910·2019-08-30 15:44
閱讀 2460·2019-08-30 13:15
閱讀 1034·2019-08-30 13:04
閱讀 1634·2019-08-29 15:09
閱讀 3956·2019-08-26 18:26