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

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

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

      前端面試題:如何實(shí)現(xiàn)事件總線 Event Bus

      介紹

      通常作為多個(gè)模塊間的通信機(jī)制,相當(dāng)于一個(gè)事件管理中心,一個(gè)模塊發(fā)送消息,其它模塊接受消息,就達(dá)到了通信的作用。

      原理

      本質(zhì)上是采用了發(fā)布-訂閱的設(shè)計(jì)模式,比如多個(gè)模塊 A、B、C 訂閱了一個(gè)事件 EventX,然后某一個(gè)模塊 X 在事件總線發(fā)布了這個(gè)事件,那么事件總線會(huì)負(fù)責(zé)通知所有訂閱者 A、B、C,它們都能收到這個(gè)通知消息,同時(shí)還可以傳遞參數(shù)。

      分析

      如何使用 JavaScript 來實(shí)現(xiàn)一個(gè)簡單版本的 Event Bus

      1. 創(chuàng)建一個(gè)類
      2. 又一個(gè)事件池,用來保存發(fā)布的事件
      3. 有一個(gè)發(fā)布的方法,將事件發(fā)布
      4. 有一個(gè)訂閱的監(jiān)聽機(jī)制,來觸發(fā)事件的回調(diào)
      5. 有取消訂閱的機(jī)制
      6. 有只訂閱一次的機(jī)制

      實(shí)現(xiàn)

      創(chuàng)建一個(gè)類

      class EventBus {}
      

      創(chuàng)建一個(gè)事件池

      class EventBus {
        private events: {
          [key: string]: Array<{fn: Function, isOnce: boolean}>
        }
      
        constructor() {
          this.events = {}
        }
      }
      

      發(fā)布事件

      1. 第一個(gè)參數(shù)是事件的KEY值, 剩余是接收事件的參數(shù)
      2. 在處理事件池中的監(jiān)聽時(shí),將只監(jiān)聽一次的事件去除
      class EventBus {
        private events: {
          [key: string]: Array<{fn: Function, isOnce: boolean}>
        }
      
        constructor() {
          this.events = {}
        }
        emit(type: string, ...args: any[]) {
          const fnList = this.events[type]
          if (fnList == null) return
          this.events[type] = fnList.filter(item => {
            const {fn, isOnce} = item
            fn(...args)
            return !isOnce
          })
        }
      }
      

      訂閱事件

      class EventBus {
        private events: {
          [key: string]: Array<{fn: Function, isOnce: boolean}>
        }
      
        constructor() {
          this.events = {}
        }
        on(type: string, fn: Function, isOnce:boolean=false){
          const events = this.events
          if (events[type] == null) {
            this.events[type] = []
          }
          this.events[type].push({fn: fn, isOnce})
        }
        emit(type: string, ...args: any[]) {
          const fnList = this.events[type]
          if (fnList == null) return
          this.events[type] = fnList.filter(item => {
            const {fn, isOnce} = item
            fn(...args)
            return !isOnce
          })
        }
      }
      

      只訂閱一次

      class EventBus {
        private events: {
          [key: string]: Array<{fn: Function, isOnce: boolean}>
        }
      
        constructor() {
          this.events = {}
        }
        on(type: string, fn: Function, isOnce:boolean=false){
          const events = this.events
          if (events[type] == null) {
            this.events[type] = []
          }
          this.events[type].push({fn: fn, isOnce})
        }
        once(type: string, fn: Function) {
          this.on(type, fn, true)
        }
        emit(type: string, ...args: any[]) {
          const fnList = this.events[type]
          if (fnList == null) return
          this.events[type] = fnList.filter(item => {
            const {fn, isOnce} = item
            fn(...args)
            return !isOnce
          })
        }
      }
      

      取消訂閱

      class EventBus {
        private events: {
          [key: string]: Array<{fn: Function, isOnce: boolean}>
        }
      
        constructor() {
          this.events = {}
        }
        on(type: string, fn: Function, isOnce:boolean=false){
          const events = this.events
          if (events[type] == null) {
            this.events[type] = []
          }
          this.events[type].push({fn: fn, isOnce})
        }
        once(type: string, fn: Function) {
          this.on(type, fn, true)
        }
        emit(type: string, ...args: any[]) {
          const fnList = this.events[type]
          if (fnList == null) return
          this.events[type] = fnList.filter(item => {
            const {fn, isOnce} = item
            fn(...args)
            return !isOnce
          })
        }
        off(type: string, fn: Function) {
          this.events[type] = this.events[type].filter(item => {
            return item.fn !== fn
          })
        }
      }
      

      取消訂閱某個(gè)事件

      class EventBus {
        private events: {
          [key: string]: Array<{fn: Function, isOnce: boolean}>
        }
      
        constructor() {
          this.events = {}
        }
        on(type: string, fn: Function, isOnce:boolean=false){
          const events = this.events
          if (events[type] == null) {
            this.events[type] = []
          }
          this.events[type].push({fn: fn, isOnce})
        }
        once(type: string, fn: Function) {
          this.on(type, fn, true)
        }
        emit(type: string, ...args: any[]) {
          const fnList = this.events[type]
          if (fnList == null) return
          this.events[type] = fnList.filter(item => {
            const {fn, isOnce} = item
            fn(...args)
            return !isOnce
          })
        }
        off(type: string, fn: Function) {
          // 如果沒傳 函數(shù)就是解除所有
          if (!fn) {
            this.events[type] = []
          }else {
            this.events[type] = this.events[type].filter(item => {
              return item.fn !== fn
            })
          }
        }
      }
      

      單例模式應(yīng)用

      在上層實(shí)例中單例

      將事件總線引入到上層實(shí)例使用,只需要保證在一個(gè)上層實(shí)例中只有一個(gè) EventBus,如果上層實(shí)例有多個(gè),意味著有多個(gè)事件總線,但是每個(gè)上層實(shí)例管控自己的事件總線。
      首先在上層實(shí)例中建立一個(gè)變量用來存儲事件總線,只在第一次使用時(shí)初始化,后續(xù)其他模塊使用事件總線時(shí)直接取得這個(gè)事件總線實(shí)例。

      // 上層實(shí)例
      class LWebApp {
        private _eventBus?: EventBus;
      
        constructor() {}
      
        public getEventBus() {
          // 第一次初始化
          if (this._eventBus == undefined) {
            this._eventBus = new EventBus();
          }
      
          // 后續(xù)每次直接取唯一一個(gè)實(shí)例,保持在LWebApp實(shí)例中單例
          return this._eventBus;
        }
      }
      
      // 使用
      const eventBus = new LWebApp().getEventBus();
      
      

      在全局中單例

      有時(shí)候我們希望不管哪一個(gè)模塊想使用我們的事件總線,我們都想這些模塊使用的是同一個(gè)實(shí)例,這就是全局單例,這種設(shè)計(jì)能更容易統(tǒng)一管理事件。
      寫法同上面的類似,區(qū)別是要把 _eventBus 和 getEventBus 轉(zhuǎn)為靜態(tài)屬性。使用時(shí)無需實(shí)例化 EventBusTool 工具類,直接使用靜態(tài)方法就行了。

      // 上層實(shí)例
      class EventBusTool {
        private static _eventBus?: EventBus;
      
        constructor() {}
      
        public static getEventBus(): EventBus {
          // 第一次初始化
          if (this._eventBus == undefined) {
            this._eventBus = new EventBus();
          }
      
          // 后續(xù)每次直接取唯一一個(gè)實(shí)例,保持全局單例
          return this._eventBus;
        }
      }
      
      // 使用
      const eventBus = EventBusTool.getEventBus();
      
      

      2周刷完100道前端優(yōu)質(zhì)面試真題,雙越老師力作

      鏈接:https://pan.baidu.com/s/1Fr4TUipNKGyaZxssKIkc3w
      提取碼:ylsp

      也歡迎使用我的小程序,驚喜不斷!

      xcxm.jpg

      posted on 2023-02-13 16:52  不銹鋼子  閱讀(422)  評論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 亚洲国产精品老熟女乱码| 欧美饥渴熟妇高潮喷水| √天堂资源地址在线官网| 国产熟女精品一区二区三区| 亚洲成色精品一二三区| 四虎国产精品永久在线下载| 好爽好紧好大的免费视频| 台前县| 久久久无码精品亚洲日韩蜜臀浪潮| 91无码人妻精品一区二区蜜桃 | 国产三级精品三级在线观看| 国产成人免费一区二区三区| 日本精品aⅴ一区二区三区| 樱花草视频www日本韩国| 江川县| 国产在线无码精品无码| 一个人免费观看WWW在线视频| 国产欧美日韩免费看AⅤ视频| 国产精品一区在线免费看| 99久久精品美女高潮喷水| 色综合色综合久久综合频道| 熟女系列丰满熟妇AV| 亚洲av永久无码精品网站| 亚洲女人天堂成人av在线| 日本免费一区二区三区最新vr | 口爆少妇在线视频免费观看| 亚洲gv猛男gv无码男同| 色综合久久精品亚洲国产| 日日噜噜夜夜狠狠视频| 亚洲蜜臀av乱码久久| 亚洲综合一区二区国产精品| 农村欧美丰满熟妇xxxx| 冕宁县| 欧美亚洲另类制服卡通动漫| 国产高清乱码又大又圆| 日夜啪啪一区二区三区| 少妇午夜啪爽嗷嗷叫视频| 国产一区二区三区黄色片| 国产a在视频线精品视频下载| 亚洲第一二三区日韩国产| 国产精品中文字幕观看|