<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [JS] 事件總線

      事件總線與發布訂閱模式

      事件總線是對發布-訂閱模式的一種實現。

      發布-訂閱模式定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都將得到通知。

      發布-訂閱模式實現了松耦合,發布者不是直接將消息發送給訂閱者,而是經過了一個中間的代理,事件總線就是一種中間代理的實現。

      事件總線維護了一個事件列表,訂閱者可以訂閱某一個事件,并指定一個回調(回調的具體實現在訂閱者內部);

      每個事件又維護了一個依賴列表,發布者可以“觸發”一個事件,事件總線負責遍歷該事件的依賴列表,調用每一個當初訂閱者訂閱時指定的回調函數。

      image-20231124223019810 image-20231124223036722

      在 JS 中實現Event Bus

      定義一個EventBus類:

      class EventBus{}
      

      需要維護一個事件列表,在初始化事件總線對象的時候創建。

      對于每一個事件,我們需要記錄它的事件名(string類型),還需要記錄該事件的依賴列表(Array<Function>類型),依賴列表其實就是各個訂閱者的回調函數的列表。

      這采用了一個對象來記錄多個事件,剛好鍵值對就是事件名:依賴列表

      constructor(){
          this.eventObject = {};
      }
      

      實現訂閱

      每一次訂閱需要指定訂閱的事件名發布時要觸發的回調函數

      • 如果指定的事件不存在,則添加一個事件,并推入該新依賴(回調函數)。
      • 如果指定的事件存在,則直接推入新依賴(回調函數)
      subscribe(eventName, callback){
          if(!this.eventObject[eventName]){
              this.eventObject[eventName] = [];
          }
          this.eventObject[eventName].push(callback);
      }
      

      實現發布

      發布也要考慮到指定的事件是否存在。如果不存在,則中斷并返回警告;如果存在指定事件,則依次調用事件的依賴列表(回調列表)。

      publish(eventName){
          const callbackList = this.eventObject[eventName];
          if(!callbackList)return console.warn(eventName + " Not Found!");
          for(let callback of callbackList){
              callback();
          }
      }
      

      匯總如下

      class EventBus{
          constructor(){
              this.eventObject = {};
          }
      
          /**
           * @param {string} eventName 
          */
          publish(eventName){
              const callbackList = this.eventObject[eventName];
      
              if(!callbackList)return console.warn(eventName + " Not Found!");
              
              for(let callback of callbackList){
                  callback();
              }
          }
      
          /**
           * @param {string} eventName 
           * @param {Function} callback 
          */
          subscribe(eventName, callback){
              if(!this.eventObject[eventName]){
                  this.eventObject[eventName] = [];
              }
      
              this.eventObject[eventName].push(callback);
          }
      }
      

      優化Event Bus的實現

      在發布時傳遞參數

      使用...args介紹不定長參數列表,在發布時傳入,并在調用回調函數列表的時候依次傳入。

      /**
      * @param {string} eventName 
      */
      publish(eventName, ...args){
          const callbackList = this.eventObject[eventName];
      
          if(!callbackList)return console.warn(eventName + " Not Found!");
      
          for(let callback of callbackList){
              callback(...args);
          }
      }
      

      提供取消訂閱的操作

      在訂閱者調用subscribe方法訂閱事件的時候,返回一個用于取消訂閱的unSubscribe方法。

      在實現事件的回調函數列表的時候,需要為每一個回調函數添加一個id,方便以后查詢并刪除該回調函數。

      這里將訂閱的回調函數列表換成用對象結構存儲,因為在數組中刪除某個中間元素較麻煩且耗時,效率不如對象結構的delete刪除鍵值對。

      換成對象結構存儲后,鍵值對表示:id:回調函數

      class EventBus{
          constructor(){
              // 初始化事件列表
              this.eventObject = {};
              // 回調函數列表的 id
              this.callbackId = 0;
          }
      
          /**
           * @param {string} eventName 
          */
          publish(eventName, ...args){
              // 取出該事件的回調函數列表(對象)
              const callbackObject = this.eventObject[eventName];
      
              if(!callbackObject)return console.warn(eventName + " Not Found!");
              
              // 執行每一個回調函數,這里的id是對象的key
              for(let id in callbackObject){
                  callbackObject[id](...args);
              }
          }
      
          /**
           * @param {string} eventName 
           * @param {Function} callback 
           * @returns {{
           *      unSubscribe: Function
           * }}
          */
          subscribe(eventName, callback){
              if(!this.eventObject[eventName]){
                  this.eventObject[eventName] = {};
              }
              // 為當前事務的回調函數申請一個專屬id
              const id = this.callbackId++;
              // 綁定回調函數
              this.eventObject[eventName][id] = callback;
              // 生成取消訂閱的函數
              const unSubscribe = ()=>{
                  // 刪除該回調函數
                  delete this.eventObject[eventName][id];
                  // 如果該事件的回調函數都刪完了,則順便刪除事件列表中的事件
                  if(Object.keys(this.eventObject[eventName]).length === 0){
                      delete this.eventObject[eventName];
                  }
              }
              
              return {unSubscribe};
          }
      }
      

      清除某個事件

      /**
      * @description 清除某事件
      * @param {string} eventName
      */
      clear(eventName){
          if(!this.eventObject.hasOwnProperty(eventName)){
              return console.warn(eventName + " Not Found!");
          }
          delete this.eventObject[eventName];
      }
      
      posted @ 2023-11-25 14:20  feixianxing  閱讀(258)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲 日本 欧洲 欧美 视频| 暖暖影院日本高清...免费| 国内偷自第一区二区三区| 国产超碰无码最新上传| 九九九精品成人免费视频小说| 一本色道久久东京热| 日韩有码中文字幕一区二区 | 国产免费高清69式视频在线观看| 99午夜精品亚洲一区二区| 男女啪啪免费观看网站| 欧美成人精品手机在线| 国产jjizz女人多水喷水| 国产不卡的一区二区三区| 成人午夜av在线播放| 午夜免费福利小电影| 99re热这里只有精品视频| 日本无产久久99精品久久| 亚洲成av人片无码天堂下载| 女人被狂躁c到高潮喷水一区二区| 麻豆精品在线| 在线中文字幕国产一区| 她也色tayese在线视频| 国产精品三级黄色小视频| 吉林省| 色猫咪av在线网址| 国产AV影片麻豆精品传媒| 亚洲精品国偷自产在线| 亚洲中文字幕无码专区| 精品 无码 国产观看| 福利一区二区在线观看| 国产精品天天狠天天看| 中文字幕结果国产精品| 精品国产一区二区三区国产区 | 国产乱人对白| 国产精品一区二区不卡视频| 国产精品欧美福利久久| 亚洲欧洲日产国无高清码图片| 人人爽天天碰天天躁夜夜躁| Y111111国产精品久久久| 亚洲sm另类一区二区三区| 康马县|