摘要:解決命名空間問題暫不管,刪除訂閱問題這個(gè)用處不大目前我們先著手解決這個(gè)問題對應(yīng)的消息么有被人訂閱沒有傳入具體的回調(diào)函數(shù)表示取消對應(yīng)的所有訂閱反向遍歷刪除訂閱回調(diào)函數(shù)這個(gè)對象,能夠解決大部分事件模擬的問題。
訂閱發(fā)布模式如果按數(shù)學(xué)翻譯其實(shí)就是.一對多的映射關(guān)系.怎么解釋呢? 就是一個(gè)開關(guān),同時(shí)并聯(lián)幾個(gè)燈泡(在不同房間),觸發(fā)的時(shí)候,幾個(gè)燈泡都會(huì)得到指令,然后執(zhí)行發(fā)光的行為。
訂閱發(fā)布模式這種模式在js里面有這天然的優(yōu)勢,因?yàn)閖s本身就是事件驅(qū)動(dòng)型語言。比如,頁面上有一個(gè)button, 你點(diǎn)擊一下就會(huì)觸發(fā)上面的click事件,而此時(shí)有一部分程序正在監(jiān)聽這個(gè)事件,隨之觸發(fā)相關(guān)的處理程序.
var button = $("#button"); button.on("click",function(){ console.log("I am pressing the button"); });
事實(shí)上,我們也早就熟悉這個(gè)模式了,只是不知道這叫什么(訂閱發(fā)布模式 又名 觀察者模式).
這個(gè)模式最大的一個(gè)好處就在于,能夠解耦回調(diào)函數(shù),讓你的程序看起來更美觀(雖然現(xiàn)在有Promise和Deferred幫忙,但是不徹底)。
說了點(diǎn)理論,來些干貨。(以下將訂閱發(fā)布模式簡稱為觀察者模式).
觀察者模式無非就兩個(gè)部分,一個(gè)訂閱(監(jiān)聽程序),一個(gè)發(fā)布(觸發(fā)事件).而他們中間的鏈接樞紐就是事件。 通常來說,我們可以自定義一個(gè)觀察者模式--使用自定義事件.
(由于IE過于SB,我就不想說他的事了,下面這些適用于chrome, iE9+,ff等其他現(xiàn)代瀏覽器中)
// Create the event. //創(chuàng)建一個(gè)事件 var event = document.createEvent("Event"); //Event是自定義的事件名 // Define that the event name is "build". event.initEvent("build", true, true); //這里是初始化事件, //就是些參數(shù)而已. // Listen for the event. elem.addEventListener("build", function (e) { //給事件添加監(jiān)聽 // e.target matches elem }, false); // target can be any Element or other EventTarget. elem.dispatchEvent(event); //觸發(fā)事件
大致就是這幾個(gè)步驟,由于這樣寫,太非人道了。所以這里映入jquery的trigger觸發(fā)方式(大哥就是大哥~)
在jquery的事件處理中,幾個(gè)基本和事件相關(guān)的API需要熟悉。一個(gè)是on,一個(gè)是trigger.
$(".ele").on("click",function(){ console.log("clicking"); }); $(".ele").trigger("click");
這是一個(gè)基本的使用,使用trigger來觸發(fā)事件.
但是誰尼瑪無聊到連click自己手動(dòng)觸發(fā)啊,這個(gè)例子只是講解。現(xiàn)在說一下精華-自定義事件.
在jquery里面,可以直接使用on來進(jìn)行自定義事件的模擬。
ele.on("stimulate",function(){ //訂閱一個(gè)事件 ...do sth }); ele.trigger("stimulate"); //發(fā)布一個(gè)事件
這里trigger只是起到一個(gè)開關(guān)的作用,那么我想要他變?yōu)橐粋€(gè)管道可以嗎?
absolutely!!!
在trigger里面還有第二個(gè)參數(shù)可以選擇,即[data]
$(document.body).on("stimulate",function(event,name1,name2){ //和節(jié)點(diǎn)有關(guān)的事件里,第一個(gè)參數(shù)永遠(yuǎn)是event console.log(name1,name2); //"jimmy","sam" }); $(document.body).trigger("stimulate",["jimmy","sam"]);
而且如果你自定義事件過多,起名也是件死人的事。所以牛逼的jq會(huì)幫你把命名空間處理好.
ele.on("stimulate.jimmy.sam",function(){ //使用"."鏈接 ...do sth });
他的作用域就是sam>jimmy>stimulate這樣一個(gè)關(guān)系.
詳情可以參考: Aron大神些的jquery事件解析。這里我直接把trigger的源碼貼出來吧.以供參考.
trigger源碼
其實(shí)上面的自定義事件的用法也非常有限,因?yàn)槿绻褂靡粋€(gè)節(jié)點(diǎn)作為載體的話,這樣的成本也太大了。所以一般在業(yè)內(nèi)已經(jīng)有成熟的自定義事件的插件了.
不過為了深入理解觀察者模式,我們一步一步來.(為了裝逼)
經(jīng)過上面的唐僧咒,大家也應(yīng)該差不多熟悉這個(gè)模式的一些關(guān)鍵部分。訂閱,發(fā)布,事件。
好,我們就這3個(gè)部分來自己模擬一個(gè)。
//摘自alloyTeam團(tuán)隊(duì)的曾探·著 var imitate = (function() { var imitate = { clientList: [], listen: function(key, fn) { if (!this.clientList[key]) { this.clientList[key] = []; } this.clientList[key].push(fn); }, trigger: function() { var key = [].shift.call(arguments); var fns = this.clientList[key]; // 如果沒有對應(yīng)的綁定消息 if (!fns || fns.length === 0) { return false; } for (var i = 0, fn; fn = fns[i++];) { // arguments 是 trigger帶上的參數(shù) fn.apply(this, arguments); } } } return function() { return Object.create(imitate); } })(); var eventModel = imitate(); //得到上面的對象 eventModel.listen("jimmy",function(){console.log("jimmy");}); //jimmy eventModel.trigger("jimmy");
恩,這樣下來皆可以和重重的節(jié)點(diǎn)說拜拜了。直接使用imitate就可以進(jìn)行事件的模擬,而且超快.
當(dāng)然,這樣寫改進(jìn)的空間還是挺大的。解決命名空間問題(暫不管),刪除訂閱問題(這個(gè)用處不大)...目前我們先著手解決這個(gè)問題.
var Event = (function() { var clientList = {}; var listen, trigger, remove; listen = function(key, fn) { if (!clientList[key]) { clientList[key] = []; } clientList[key].push(fn); }; trigger = function() { var key = [].shift.call(arguments); var fns = clientList[key]; if (!fns || fns.length === 0) { return false; } for (var i = 0, fn; fn = fns[i++];) { fn.apply(this, arguments); } }; remove = function(key, fn) { var fns = clientList[key]; // key對應(yīng)的消息么有被人訂閱 if (!fns) { return false; } // 沒有傳入fn(具體的回調(diào)函數(shù)), 表示取消key對應(yīng)的所有訂閱 if (!fn) { fns && (fns.length = 0); } else { // 反向遍歷 for (var i = fns.length - 1; i >= 0; i--) { var _fn = fns[i]; if (_fn === fn) { // 刪除訂閱回調(diào)函數(shù) fns.splice(i, 1); } } } }; return { listen: listen, trigger: trigger, remove: remove } }());
這個(gè)Event對象,能夠解決大部分事件模擬的問題。說了這么多,md,實(shí)例嘞。。。等等。馬上來
發(fā)布訂閱模式的實(shí)戰(zhàn)如果大家寫過登錄框(異步登錄哈),應(yīng)該知道.登錄框和header的部分是完全不同的兩個(gè)部分。這個(gè)場景就很適合發(fā)布訂閱模式了。
看一下。如果沒有發(fā)布訂閱模式的代碼:
login.on("click",function(){ var name = $(".username").val().trim; http.login(name) //使用異步Deferred書寫 .then(function(data){ //以下填寫亂七八糟的處理 changeName(); changeAvtar(); changeStatus(); ... }) });
使用發(fā)布訂閱模式
login.on("click",function(){ var name = $(".username").val().trim; http.login(name) //使用異步Deferred書寫 .then(function(data){ Event.trigger("login",data); //發(fā)布我登錄成功的狀態(tài),并傳入?yún)?shù) }) }); var header = (function() { Event.listen("login", function(data) { header.changeAvator(data); }) return { changeAvator: function(data) { ...換頭像 } } })(); var bar = (function() { Event.listen("login", function(data) { bar.changeName(data); }) return { changeName: function(data) { ...換名字 } } })();
可以清楚的看到,如果你的登錄狀態(tài)改變了的話,會(huì)有一系列的訂閱程序發(fā)生.而且每個(gè)訂閱之間互不干擾,你可以隨便添加或者刪除訂閱,這都不會(huì)影響你的登錄的執(zhí)行邏輯. 當(dāng)然發(fā)布訂閱的使用肯定不會(huì)僅僅局限于,登錄狀態(tài)的改變。還可以應(yīng)用于,模塊間信息的傳遞,分頁頁面的渲染等。但是使用的時(shí)候,一定要慎重,因?yàn)槟阌嗛喌脑蕉啵琤ug的查找也會(huì)越復(fù)雜。所以,發(fā)布訂閱模式使用的時(shí)候,希望大家好好想一想,不要為了模式而去模式。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91595.html
摘要:由主體和觀察者組成,主體負(fù)責(zé)發(fā)布事件,同時(shí)觀察者通過訂閱這些事件來觀察該主體。主體并不知道觀察者的任何事情,觀察者知道主體并能注冊事件的回調(diào)函數(shù)。總的來說,觀察者模式所做的工作就是在解耦,讓耦合的雙方都依賴于抽象,而不是依賴于具體。 發(fā)布訂閱模式 發(fā)布訂閱模式又叫觀察者模式(Publish/Subscribe),它定義了一種一對多的關(guān)系,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象,這個(gè)主題...
摘要:觀察者模式介紹觀察者模式又稱發(fā)布訂閱模式,它定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象發(fā)生改變的時(shí)候,所依賴它的對象都能得到通知。關(guān)于內(nèi)部的觀察者模式可以參數(shù)這篇文檔。總結(jié)總之,觀察者模式在中的使用是非常廣泛的。 javascript觀察者模式 介紹 觀察者模式又稱發(fā)布-訂閱模式,它定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象發(fā)生改變的時(shí)候,所依賴它的對象都能得到通知。例如:我們訂閱...
摘要:期設(shè)計(jì)模式如何理解觀察者發(fā)布訂閱模式定義觀察者模式又叫發(fā)布訂閱模式,它定義了一種一對多的關(guān)系,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象,這個(gè)主題對象的狀態(tài)發(fā)生變化時(shí)就會(huì)通知所有的觀察者對象,使得它們能夠自動(dòng)更新自己生活實(shí)例理解你今天去看一個(gè) 20190411期 設(shè)計(jì)模式-如何理解觀察者(發(fā)布訂閱)模式? 定義: 觀察者模式又叫發(fā)布訂閱模式(Publish/Subscribe),它定義了一...
摘要:觀察者模式機(jī)動(dòng)建立一種對象與對象之間的依賴關(guān)系,一個(gè)對象發(fā)生改變時(shí)將自動(dòng)通知其他對象,其他對象將相應(yīng)做出反應(yīng)。 觀察者模式模式簡介 觀察者模式(又被稱為發(fā)布-訂閱(Publish/Subscribe)模式,屬于行為型模式的一種,它定義了一種一對多的依賴關(guān)系,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象。這個(gè)主題對象在狀態(tài)變化時(shí),會(huì)通知所有的觀察者對象,使他們能夠自動(dòng)更新自己。 觀察者模式機(jī)動(dòng)...
摘要:實(shí)際上,設(shè)計(jì)模式就是通過面向?qū)ο蟮奶匦裕瑢⑦@些角色解耦觀察者模式本質(zhì)上就是一種訂閱發(fā)布的模型,從邏輯上來說就是一對多的依賴關(guān)系。在添加一個(gè)觀察者時(shí),把被主題被觀察者對象以構(gòu)造函數(shù)的形式給傳入了觀察者。 每個(gè)角色都對應(yīng)這一個(gè)類,比如觀察者模式,觀察者對應(yīng)著觀察者類,被觀察者對應(yīng)著被觀察者類。實(shí)際上,設(shè)計(jì)模式就是通過面向?qū)ο蟮奶匦裕瑢⑦@些角色解耦 觀察者模式本質(zhì)上就是一種訂閱 / 發(fā)布的模...
閱讀 2674·2021-11-24 09:38
閱讀 1985·2019-08-30 15:53
閱讀 1246·2019-08-30 15:44
閱讀 3237·2019-08-30 14:10
閱讀 3587·2019-08-29 16:29
閱讀 1808·2019-08-29 16:23
閱讀 1107·2019-08-29 16:20
閱讀 1476·2019-08-29 11:13