<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] # 發布-訂閱模式 又稱為觀察者模式,它定義對象間的一種一對多的依賴關系,當一個對象的狀態發生 改變的時,所有依賴于它的對象都將得到通知。一為時間上解耦,二為對象之間的解 耦。 ## DOM事件 DOM元素上的事件函數,就是如此。當我們為一個元素增加一個事件時,等到這個時 間觸發后,就會執行我們的回調函數,同時也能夠移除該事件。 ## 自定義事件 發布-訂閱模式的通用實現 ```javascript var event = { clientList: {}, listen: function(key, fn){ // 訂閱 if(!this.clientList[key]){ this.clientList[key] = {}; } this.clientList[key].push(fn); }, trigger: function(){ // 發布 var key = Array.prototype.shift.call(arguments), fns = this.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 = this.clientList[key]; if(!fns || fns.length === 0){ return false; } if(!fn){ fns && (fns.lengthss = 0); // 如果沒有傳 具的回調函數,表示需要取消key對應消息的所有訂閱 }else{ for(var l = fns.length - 1; l >=0; l--){ // 反向遍歷 var _fn = fns[l]; if(_fn === fn){ fns.splice(l, 1); // 刪除訂閱者的回調函數 } } } } }; // 再定義 個installEvent函數,這個函數可以給所有的對象都動態安裝發布-訂閱功能 var installEvent = function(obj){ for(var i in event){ event[i] = obj[i]; } }; var salesOffices = { ... }; installEvent(salesOffices); salesOffices.listen('event1'); salesOffices.trigger('event1'); salesOffices.remove('event1'); ``` ## 全局的發布-訂閱對象 發布-訂閱模式可以用一個全局的Event對象來實現,訂閱者不需要了解消息來自哪個 發布者,發布者也不知道消息會推送給哪些訂閱者,Event作為一個類似“中介 者”的角色,把訂閱者和發布者聯系起來。 ```javascript var Event = (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(var i=0; fn; fn = fns[i++]){ fn.apply(this, arguments); } }; remove = function(key, fn){ var fns = clientList[key]; if(!fns || fns.length === 0){ return false; } if(!fn){ fns && (fns.lengthss = 0); // 如果沒有傳 具的回調函數,表示需要取消key對應消息的所有訂閱 }else{ for(var l = fns.length - 1; l >=0; l--){ // 反向遍歷 var _fn = fns[l]; if(_fn === fn){ fns.splice(l, 1); // 刪除訂閱者的回調函數 } }; return { listen: listen, trigger: trigger, remove: remove } })(); Event.listen('event1'); Event.trigger('event1'); Event.remove('event1'); ``` ## 模塊間通信 模塊之間如果用了太多的全局發布-訂閱模式來通信,那么模塊與模塊之間的聯系就 被隱藏到了背后,我們最終會搞不清楚消息來自哪個模塊,或者消息會流向哪些模 塊,這又會給我們的維護帶來一些麻煩,也許某個模塊的作用就是暴露一些接口給其 他模塊調用。 ## 必須先訂閱再發布嗎 在某些情況下,需要先將消息保存下來,等到有對象來訂閱它的時候,再重新把消息 發布給訂閱者。就如果離線消息一樣。 我們需要建立一個存放離線事件的堆棧,當事件發布的時候,如果此時還沒有訂閱者 來訂閱這個事件,我們暫時把發布事件的動作包裹在一個函數里,這些包裝函數 存入堆棧中,等到終于有對象來訂閱此事件的時候,我們將遍歷堆棧并且依次執行這 些包裝函數,也就是重新發布里面的事件。當然離線事件的生命周期只有一次。 ## 全局事件的命名沖突 ```javascript //全局作用域下的發布訂閱模式 (function(){ var Event = (function{ var global = this, Modal, _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(const 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] === 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,cache,fn); }, 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 : , one: , remove: , listen:, trigger:, var event = this.create(); event.trigger.apply(this,arguments); } }(); return Event; }()); Event.create('namespace1').listen('event'); Event.create('namespace1').trigger('event'); ``` ## JavaScript 實現發布-訂閱模式的便利性 - 推模型:是指在事件發生時,發布者一次性把所有更改的狀態和數據都推送給訂 閱者。 - 拉模型:發布者僅僅通知訂閱者事件已經發生了,此外發布者要提供一些公開接口共訂閱者來主動拉取數據。 剛好在JavaScript中, arguments 可以很方便地表示參數列表,所以我們一般都會選 擇推模型,使用 Function.prototype.apply 方法把所有參數都推送給訂閱者。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看