




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Javascript發(fā)布訂閱模式介紹發(fā)布訂閱模式介紹
發(fā)布---訂閱模式又叫觀察者模式,它定義了對(duì)象間的一種一對(duì)多的關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象,當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí),所有依賴于它的對(duì)象都將得到通知。
現(xiàn)實(shí)生活中的發(fā)布-訂閱模式;
比如小紅最近在淘寶網(wǎng)上看上一雙鞋子,但是呢聯(lián)系到賣家后,才發(fā)現(xiàn)這雙鞋賣光了,但是小紅對(duì)這雙鞋又非常喜歡,所以呢聯(lián)系賣家,問(wèn)賣家什么時(shí)候有貨,賣家告訴她,要等一個(gè)星期后才有貨,賣家告訴小紅,要是你喜歡的話,你可以收藏我們的店鋪,等有貨的時(shí)候再通知你,所以小紅收藏了此店鋪,但與此同時(shí),小明,小花等也喜歡這雙鞋,也收藏了該店鋪;等來(lái)貨的時(shí)候就依次會(huì)通知他們;
在上面的故事中,可以看出是一個(gè)典型的發(fā)布訂閱模式,賣家是屬于發(fā)布者,小紅,小明等屬于訂閱者,訂閱該店鋪,賣家作為發(fā)布者,當(dāng)鞋子到了的時(shí)候,會(huì)依次通知小明,小紅等,依次使用旺旺等工具給他們發(fā)布消息;
發(fā)布訂閱模式的優(yōu)點(diǎn):
1.支持簡(jiǎn)單的廣播通信,當(dāng)對(duì)象狀態(tài)發(fā)生改變時(shí),會(huì)自動(dòng)通知已經(jīng)訂閱過(guò)的對(duì)象。
比如上面的列子,小明,小紅不需要天天逛淘寶網(wǎng)看鞋子到了沒(méi)有,在合適的時(shí)間點(diǎn),發(fā)布者(賣家)來(lái)貨了的時(shí)候,會(huì)通知該訂閱者(小紅,小明等人)。
2.發(fā)布者與訂閱者耦合性降低,發(fā)布者只管發(fā)布一條消息出去,它不關(guān)心這條消息如何被訂閱者使用,同時(shí),訂閱者只監(jiān)聽(tīng)發(fā)布者的事件名,只要發(fā)布者的事件名不變,它不管發(fā)布者如何改變;同理賣家(發(fā)布者)它只需要將鞋子來(lái)貨的這件事告訴訂閱者(買家),他不管買家到底買還是不買,還是買其他賣家的。只要鞋子到貨了就通知訂閱者即可。
對(duì)于第一點(diǎn),我們?nèi)粘9ぷ髦幸步?jīng)常使用到,比如我們的ajax請(qǐng)求,請(qǐng)求有成功(success)和失敗(error)的回調(diào)函數(shù),我們可以訂閱ajax的success和error事件。我們并不關(guān)心對(duì)象在異步運(yùn)行的狀態(tài),我們只關(guān)心success的時(shí)候或者error的時(shí)候我們要做點(diǎn)我們自己的事情就可以了~
發(fā)布訂閱模式的缺點(diǎn):
創(chuàng)建訂閱者需要消耗一定的時(shí)間和內(nèi)存。雖然可以弱化對(duì)象之間的聯(lián)系,如果過(guò)度使用的話,反而使代碼不好理解及代碼不好維護(hù)等等。
如何實(shí)現(xiàn)發(fā)布--訂閱模式?
首先要想好誰(shuí)是發(fā)布者(比如上面的賣家)。然后給發(fā)布者添加一個(gè)緩存列表,用于存放回調(diào)函數(shù)來(lái)通知訂閱者(比如上面的買家收藏了賣家的店鋪,賣家通過(guò)收藏了該店鋪的一個(gè)列表名單)。最后就是發(fā)布消息,發(fā)布者遍歷這個(gè)緩存列表,依次觸發(fā)里面存放的訂閱者回調(diào)函數(shù)。
我們還可以在回調(diào)函數(shù)里面添加一點(diǎn)參數(shù),比如鞋子的顏色,鞋子尺碼等信息;
我們先來(lái)實(shí)現(xiàn)下簡(jiǎn)單的發(fā)布-訂閱模式;代碼如下:
varshoeObj={};//定義發(fā)布者
shoeObj.list=[];//緩存列表存放訂閱者回調(diào)函數(shù)
//增加訂閱者
shoeObj.listen=function(fn){
shoeObj.list.push(fn);//訂閱消息添加到緩存列表
//發(fā)布消息
shoeObj.trigger=function(){
for(vari=0,fn;fn=this.list[i++];){
fn.apply(this,arguments);
//小紅訂閱如下消息
shoeObj.listen(function(color,size){
console.log("顏色是:"+color);
console.log("尺碼是:"+size);
//小花訂閱如下消息
shoeObj.listen(function(color,size){
console.log("再次打印顏色是:"+color);
console.log("再次打印尺碼是:"+size);
shoeObj.trigger("紅色",40);
shoeObj.trigger("黑色",42);
運(yùn)行結(jié)果如下:
打印如上截圖,我們看到訂閱者接收到發(fā)布者的每個(gè)消息,但是呢,對(duì)于小紅來(lái)說(shuō),她只想接收顏色為紅色的消息,不想接收顏色為黑色的消息,為此我們需要對(duì)代碼進(jìn)行如下改造下,我們可以先增加一個(gè)key,使訂閱者只訂閱自己感興趣的消息。
varshoeObj={};//定義發(fā)布者
shoeObj.list=[];//緩存列表存放訂閱者回調(diào)函數(shù)
//增加訂閱者
shoeObj.listen=function(key,fn){
if(!this.list[key]){
//如果還沒(méi)有訂閱過(guò)此類消息,給該類消息創(chuàng)建一個(gè)緩存列表
this.list[key]=[];
this.list[key].push(fn);//訂閱消息添加到緩存列表
//發(fā)布消息
shoeObj.trigger=function(){
varkey=Atotype.shift.call(arguments);//取出消息類型名稱
varfns=this.list[key];//取出該消息對(duì)應(yīng)的回調(diào)函數(shù)的集合
//如果沒(méi)有訂閱過(guò)該消息的話,則返回
if(!fns||fns.length===0){
return;
for(vari=0,fn;fn=fns[i++];){
fn.apply(this,arguments);//arguments是發(fā)布消息時(shí)附送的參數(shù)
//小紅訂閱如下消息
shoeObj.listen('red',function(size){
console.log("尺碼是:"+size);
//小花訂閱如下消息
shoeObj.listen('block',function(size){
console.log("再次打印尺碼是:"+size);
shoeObj.trigger("red",40);
shoeObj.trigger("block",42);
上面的代碼,我們?cè)賮?lái)運(yùn)行打印下如下:
可以看到,訂閱者只訂閱自己感興趣的消息了;
發(fā)布---訂閱模式的代碼封裝
我們知道,對(duì)于上面的代碼,小紅去買鞋這么一個(gè)對(duì)象shoeObj進(jìn)行訂閱,但是如果以后我們需要對(duì)買房子或者其他的對(duì)象進(jìn)行訂閱呢,我們需要復(fù)制上面的代碼,再重新改下里面的對(duì)象代碼;為此我們需要進(jìn)行代碼封裝;
如下代碼封裝:
varevent={
list:[],
listen:function(key,fn){
if(!this.list[key]){
this.list[key]=[];
//訂閱的消息添加到緩存列表中
this.list[key].push(fn);
trigger:function(){
varkey=Atotype.shift.call(arguments);
varfns=this.list[key];
//如果沒(méi)有訂閱過(guò)該消息的話,則返回
if(!fns||fns.length===0){
return;
for(vari=0,fn;fn=fns[i++];){
fn.apply(this,arguments);
};
我們?cè)诙x一個(gè)initEvent函數(shù),這個(gè)函數(shù)使所有的普通對(duì)象都具有發(fā)布訂閱功能,如下代碼:
varinitEvent=function(obj){
for(variinevent){
obj[i]=event[i];
};
//我們?cè)賮?lái)測(cè)試下,我們還是給shoeObj這個(gè)對(duì)象添加發(fā)布-訂閱功能;
varshoeObj={};
initEvent(shoeObj);
//小紅訂閱如下消息
shoeObj.listen('red',function(size){
console.log("尺碼是:"+size);
//小花訂閱如下消息
shoeObj.listen('block',function(size){
console.log("再次打印尺碼是:"+size);
shoeObj.trigger("red",40);
shoeObj.trigger("block",42);
如何取消訂閱事件?
比如上面的列子,小紅她突然不想買鞋子了,那么對(duì)于賣家的店鋪他不想再接受該店鋪的消息,那么小紅可以取消該店鋪的訂閱。
如下代碼:
event.remove=function(key,fn){
varfns=this.list[key];
//如果key對(duì)應(yīng)的消息沒(méi)有訂閱過(guò)的話,則返回
if(!fns){
returnfalse;
//如果沒(méi)有傳入具體的回調(diào)函數(shù),表示需要取消key對(duì)應(yīng)消息的所有訂閱
if(!fn){
fn(fns.length=0);
}else{
for(vari=fns.length-1;ii--){
var_fn=fns[i];
if(_fn===fn){
fns.splice(i,1);//刪除訂閱者的回調(diào)函數(shù)
};
測(cè)試代碼如下:
varinitEvent=function(obj){
for(variinevent){
obj[i]=event[i];
varshoeObj={};
initEvent(shoeObj);
//小紅訂閱如下消息
shoeObj.listen('red',fn1=function(size){
console.log("尺碼是:"+size);
//小花訂閱如下消息
shoeObj.listen('red',fn2=function(size){
console.log("再次打印尺碼是:"+size);
shoeObj.remove("red",fn1);
shoeObj.trigger("red",42);
運(yùn)行結(jié)果如下:
全局--發(fā)布訂閱對(duì)象代碼封裝
我們?cè)賮?lái)看看我們傳統(tǒng)的ajax請(qǐng)求吧,比如我們傳統(tǒng)的ajax請(qǐng)求,請(qǐng)求成功后需要做如下事情:
渲染數(shù)據(jù)。使用數(shù)據(jù)來(lái)做一個(gè)動(dòng)畫(huà)。
那么我們以前肯定是如下寫代碼:
$.ajax(“/index.php”,function(data){
rendedData(data);//渲染數(shù)據(jù)
doAnimate(data);//實(shí)現(xiàn)動(dòng)畫(huà)
});
假如以后還需要做點(diǎn)事情的話,我們還需要在里面寫調(diào)用的方法;這樣代碼就耦合性很高,那么我們現(xiàn)在使用發(fā)布-訂閱模式來(lái)看如何重構(gòu)上面的業(yè)務(wù)需求代碼;
$.ajax(“/index.php”,function(data){
Obj.trigger(‘success',data);//發(fā)布請(qǐng)求成功后的消息
//下面我們來(lái)訂閱此消息,比如我現(xiàn)在訂閱渲染數(shù)據(jù)這個(gè)消息;
Obj.listen(“success”,function(data){
renderData(data);
//訂閱動(dòng)畫(huà)這個(gè)消息
Obj.listen(“success”,function(data){
doAnimate(data);
});
為此我們可以封裝一個(gè)全局發(fā)布-訂閱模式對(duì)象;如下代碼:
varEvent=(function(){
varlist={},
listen,
trigger,
remove;
listen=function(key,fn){
if(!list[key]){
list[key]=[];
list[key].push(fn);
trigger=function(){
varkey=Atotype.shift.call(arguments),
fns=list[key];
if(!fns||fns.length===0){
returnfalse;
for(vari=0,fn;fn=fns[i++];){
fn.apply(this,arguments);
remove=function(key,fn){
varfns=list[key];
if(!fns){
returnfalse;
if(!fn){
fns(fns.length=0);
}else{
for(vari=fns.length-1;ii--){
var_fn=fns[i];
if(_fn===fn){
fns.splice(i,1);
return{
listen:listen,
trigger:trigger,
remove:remove
})();
//測(cè)試代碼如下:
Event.listen("color",function(size){
console.log("尺碼為:"+size);//打印出尺碼為42
Event.trigger("color",42);
理解模塊間通信
我們使用上面封裝的全局的發(fā)布-訂閱對(duì)象來(lái)實(shí)現(xiàn)兩個(gè)模塊之間的通信問(wèn)題;比如現(xiàn)在有一個(gè)頁(yè)面有一個(gè)按鈕,每次點(diǎn)擊此按鈕后,div中會(huì)顯示此按鈕被點(diǎn)擊的總次數(shù);如下代碼:
buttonid="count"點(diǎn)將我/button
divid="showcount"/div
我們中的a.js負(fù)責(zé)處理點(diǎn)擊操作及發(fā)布消息;如下JS代碼:
vara=(function(){
varcount=0;
varbutton=document.getElementById("count");
button.onclick=function(){
Event.trigger("add",count++);
})();
b.j
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 行政法學(xué)考試復(fù)習(xí)重點(diǎn)與試題
- 2025-2030年中國(guó)無(wú)機(jī)納米粒子行業(yè)市場(chǎng)現(xiàn)狀供需分析及投資評(píng)估規(guī)劃分析研究報(bào)告
- 2025-2030年中國(guó)文化用品行業(yè)市場(chǎng)發(fā)展分析及競(jìng)爭(zhēng)格局與投資前景研究報(bào)告
- 2025-2030年中國(guó)數(shù)碼攝像行業(yè)市場(chǎng)深度調(diào)研及前景趨勢(shì)與投資前景研究報(bào)告
- 2025-2030年中國(guó)數(shù)字金融行業(yè)市場(chǎng)發(fā)展現(xiàn)狀及發(fā)展趨勢(shì)與投資研究報(bào)告
- 藥師行業(yè)從業(yè)人員的考試趨勢(shì)試題及答案
- 2025-2030年中國(guó)推煤機(jī)行業(yè)市場(chǎng)現(xiàn)狀供需分析及投資評(píng)估規(guī)劃分析研究報(bào)告
- 2025-2030年中國(guó)撥碼開(kāi)關(guān)行業(yè)市場(chǎng)現(xiàn)狀供需分析及投資評(píng)估規(guī)劃分析研究報(bào)告
- 2025年申請(qǐng)執(zhí)業(yè)護(hù)士資格試題及答案
- 行政管理經(jīng)濟(jì)法考核新趨勢(shì)試題及答案
- 開(kāi)工儀式流程方案
- 2024國(guó)家安全員資格考試題庫(kù)(含答案)
- 2024-2034年中國(guó)有機(jī)復(fù)合絕緣子未來(lái)趨勢(shì)預(yù)測(cè)分析及投資規(guī)劃研究建議報(bào)告
- 《內(nèi)蒙古自治區(qū)扶持壯大嘎查村級(jí)集體經(jīng)濟(jì)項(xiàng)目和資金管理辦法》(2023修訂)
- 超星爾雅學(xué)習(xí)通《形象管理(南開(kāi)大學(xué))》2024章節(jié)測(cè)試答案
- 2023年四川省綿陽(yáng)市中考數(shù)學(xué)試卷
- 畢業(yè)設(shè)計(jì)調(diào)研總結(jié)報(bào)告
- 數(shù)字貿(mào)易學(xué) 課件 第7章 智能制造
- 景區(qū)保潔服務(wù)方案
- JJF 2109-2024標(biāo)準(zhǔn)物質(zhì)定值技術(shù)要求有機(jī)同位素稀釋質(zhì)譜法
- 強(qiáng)基計(jì)劃個(gè)人陳述范文南京大學(xué)
評(píng)論
0/150
提交評(píng)論