日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

《JavaScript设计模式与开发实践》模式篇(5)—— 观察者模式

發(fā)布時間:2025/3/8 javascript 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《JavaScript设计模式与开发实践》模式篇(5)—— 观察者模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

發(fā)布—訂閱模式又叫觀察者模式,它定義對象間的一種一對多的依賴關(guān)系,當一個對象的狀 態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知。在 JavaScript 開發(fā)中,我們一般用事件模型 來替代傳統(tǒng)的發(fā)布—訂閱模式。

故事背景

小明最近看上了一套房子,到了售樓處之后才被告知,該樓盤的房子早已售罄。好在售樓 MM 告訴小明,不久后還有一些尾盤推出,開發(fā)商正在辦理相關(guān)手續(xù),手續(xù)辦好后便可以購買。 但到底是什么時候,目前還沒有人能夠知道。 于是小明記下了售樓處的電話,以后每天都會打電話過去詢問是不是已經(jīng)到了購買時間。除 了小明,還有小紅、小強、小龍也會每天向售樓處咨詢這個問題。一個星期過后,售樓 MM 決 定辭職,因為厭倦了每天回答 1000 個相同內(nèi)容的電話。 當然現(xiàn)實中沒有這么笨的銷售公司,實際上故事是這樣的:小明離開之前,把電話號碼留在 了售樓處。售樓 MM 答應他,新樓盤一推出就馬上發(fā)信息通知小明。小紅、小強和小龍也是一 樣,他們的電話號碼都被記在售樓處的花名冊上,新樓盤推出的時候,售樓 MM 會翻開花名冊,遍歷上面的電話號碼,依次發(fā)送一條短信來通知他們。

發(fā)送短信通知就是一個典型的發(fā)布—訂閱模式,小明、小紅等購買者都是 訂閱者,他們訂閱了房子開售的消息。售樓處作為發(fā)布者,會在合適的時候遍歷花名冊上的電話號碼,依次給購房者發(fā)布消息。

代碼實現(xiàn)

  • 先訂閱后發(fā)布模式
var DEvent = (function() {var clientList = {},listen,trigger,remove;listen = function(key, fn) {if (!clientList[key]) {clientList[key] = [];}clientList[key].push(fn);};trigger = function() {var key = Array.prototype.shift.call(arguments),fns = clientList[key];if (!fns || fns.length === 0) {return false;}for (let index = 0; index < fns.length; index++) {const fn = fns[index];fn.apply(this, arguments);}};remove = function(key, fn) {var fns = clientList[key];if (!fns) {return false;}if (!fn) {fns && (fns.length = 0);} else {for (var l = fn.length - 1; l > 0 ; l--) {var _fn = fns[l];if (_fn === fn) {fns.splice(l, 1);}}}};return {listen,trigger,remove}; })(); Event.listen( 'squareMeter88', function( price ){ // 小紅訂閱消息console.log( '價格= ' + price ); // 輸出:'價格=2000000' }); Event.trigger( 'squareMeter88', 2000000 );// 售樓處發(fā)布消息 復制代碼

應用場景

  • 網(wǎng)站登錄 假如我們正在開發(fā)一個商城網(wǎng)站,網(wǎng)站里有 header 頭部、nav 導航、消息列表、購物車等模塊。這幾個模塊的渲染有一個共同的前提條件,就是必須先用 ajax 異步請求獲取用戶的登錄信息。 這是很正常的,比如用戶的名字和頭像要顯示在 header 模塊里,而這兩個字段都來自用戶登錄后 返回的信息。 至于 ajax 請求什么時候能成功返回用戶信息,這點我們沒有辦法確定。現(xiàn)在的情節(jié)看起來像 極了售樓處的例子,小明不知道什么時候開發(fā)商的售樓手續(xù)能夠成功辦下來。
$.ajax( 'http:// xxx.com?login', function(data){ // 登錄成功 login.trigger('loginSucc', data); // 發(fā)布登錄成功的消息 }); var header = (function(){ // header 模塊 login.listen( 'loginSucc', function( data){header.setAvatar( data.avatar );}); return {setAvatar: function( data ){console.log( '設置 header 模塊的頭像' );} } })();var nav = (function(){login.listen( 'loginSucc', function( data ){// nav 模塊 nav.setAvatar( data.avatar );}); return {setAvatar: function( avatar ){ console.log( '設置 nav 模塊的頭像' );} } })(); 復制代碼
  • 先發(fā)布后訂閱模式(提供創(chuàng)建命名空間的功能)
var Event = (function(){var global = this, Event,_default = 'default';Event = function(){var _listen,_trigger,_remove,_slice = Array.prototype.slice, _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, namespaceCache = {},_create,find,each = function( ary, fn ){var ret;for ( var i = 0, l = ary.length; i < l; i++ ){var n = ary[i];ret = fn.call( n, i, n); }return ret; };_listen = function( key, fn, cache ){ if ( !cache[ key ] ){cache[ key ] = []; }cache[key].push( fn );};_remove = function( key, cache, fn) {if ( cache[ key ] ){if( fn ){for( var i = cache[ key ].length; i >= 0; i-- ){if( cache[ key] [i] === fn) {cache[key].splice(i, 1);}} } else{cache[ key ] = [];}} };_trigger = function(){var cache = _shift.call(arguments),key = _shift.call(arguments), args = arguments,_self = this, ret, stack = cache[ key ];if ( !stack || !stack.length ) {return;}return each( stack, function(){return this.apply( _self, args );}); };_create = function( namespace ){var namespace = namespace || _default;var cache = {},offlineStack = [],// 離線事件ret = {listen: function(key, fn, last ){_listen(key, fn, cache );if ( offlineStack === null ){return; }if ( last === 'last' ){offlineStack.length && offlineStack.pop()(); }else{each( offlineStack, function(){this(); });}offlineStack = null; },one: function( key, fn, last ){ _remove( key, cache ); this.listen( key, fn ,last );},remove: function( key, fn ){_remove( key, cache ,fn);},trigger: function(){var fn, args,_self = this;_unshift.call( arguments, cache ); args = arguments;fn = function(){return _trigger.apply( _self, args ); };if ( offlineStack ){return offlineStack.push( fn );}return fn(); }};return namespace ?( namespaceCache[ namespace ] ? namespaceCache[ namespace] :namespaceCache[ namespace ] = ret ) : ret;};return {create: _create,one: function( key,fn, last ){ var event = this.create( );event.one( key,fn,last );},remove: function( key,fn ){var event = this.create( ); event.remove( key,fn );},listen: function( key, fn, last ){var event = this.create( ); event.listen( key, fn, last );},trigger: function(){var event = this.create( );event.trigger.apply( this, arguments ); }}; }();return Event; })(); 復制代碼

系列文章:

《JavaScript設計模式與開發(fā)實踐》最全知識點匯總大全

總結(jié)

以上是生活随笔為你收集整理的《JavaScript设计模式与开发实践》模式篇(5)—— 观察者模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。