帶你輕松搞定觀察者模式和發(fā)布訂閱模式的區(qū)別

發(fā)布日期: 2022-05-07

瀏覽量: 3337

01、模式的概念

熟悉Vue的小伙伴都知道,在Vue中使用“觀察者模式”去通知視圖更新,使用“發(fā)布訂閱”$on,$emit來(lái)實(shí)現(xiàn)自定義事件,所以搞清楚兩者之間的關(guān)系很重要啦!

02、觀察者模式

一個(gè)對(duì)象(觀察者)訂閱另一個(gè)對(duì)象(主題),當(dāng)主題被激活的時(shí)候,觸發(fā)觀察者里面的事件。

舉個(gè)例子:打點(diǎn)滴時(shí),我們會(huì)觀察吊瓶的變化,當(dāng)快打完時(shí),就要通知護(hù)士來(lái)取針。這里護(hù)士/我們就是觀察者(Obeserver),吊瓶就是被觀察者/主題。

  class Subject { //被觀察者數(shù)據(jù)--吊瓶

    constructor(name="蛋糕老師"){

    this.state = 100;

    this.name = name;

    this.obs = [] //會(huì)有多個(gè)觀察者

    }

      addObs(ob){

        this.obs.push(ob)

          }

  setState(state){ //改變狀態(tài)的方法

    this.state = state

    //要去通知觀察者去做動(dòng)作 -- 拔針 

    this.obs.forEach((ob)=>{

      ob.update(this) //讓觀察者去做更新

        })

      }

}

  class Obeserver{ //觀察者 -- 醫(yī)生

    constructor(name){

    this.name = name;

  //在觀察者里面是否可以記錄/觀察了哪些數(shù)據(jù)

         }

    update(subject){

    //醫(yī)生也有可能觀察多個(gè)打針的人 

    if (!subject.state) {

        console.log(`${this.name} 收到通知         :${subject.name} 的 帶瓶打完啦!`)

        }else {

    console.log(` ${this.name} 收到通知 :${subject.name} 的帶瓶量: ${subject.state}!`)

               }

         }

     }

     var zhiliao = new Subject();

     var hushi = new Obeserver("護(hù)士");

     var yisheng = new Obeserver("醫(yī)生")

     zhiliao.addObs(hushi) 

     zhiliao.addObs(yisheng)

     zhiliao.setState(50) 

03、發(fā)布訂閱

訂閱者把自己想要訂閱的事件注冊(cè)到調(diào)度中心,當(dāng)發(fā)布者發(fā)布事件到調(diào)度中心(就是該事件被觸發(fā)),再由調(diào)度中心統(tǒng)一調(diào)度訂閱者注冊(cè)到調(diào)度中心的處理代碼。

其實(shí)簡(jiǎn)單理解就是我們的自定義事件,比如在Vue中,Vue實(shí)例($bus)就是統(tǒng)一的調(diào)用中心,我們使用$bus去$on一個(gè)自定義事件myEvent就是發(fā)布者發(fā)布一個(gè)事件到調(diào)度中心,然后在其他地方$bus.$emit(myEvent)一下就相當(dāng)于事件被觸發(fā),然后$bus就去執(zhí)行對(duì)應(yīng)事件的回調(diào)函數(shù) 。var Event = {

    _listeners: {},    

    // 添加

    $on: function(type, fn) {

if (typeof this._listeners[type] === "undefined") {

  this._listeners[type] = [];

        }

    if (typeof fn === "function") {

      this._listeners[type].push(fn);

      }    

     return this;

    },

    // 觸發(fā)

  $emit: function(type) {

    var arrayEvent = this._listeners[type];

    if (arrayEvent instanceof Array) {

      for (var i=0, length=arrayEvent.length; i

        if (typeof arrayEvent[i] === "function") {

          arrayEvent[i]({ type: type });    

                }

            }

        }    

        return this;

    },

    // 刪除

  $off: function(type, fn) {

    var arrayEvent = this._listeners[type];

    if (typeof type === "string" && arrayEvent instanceof Array) {

      if (typeof fn === "function") {

      for (var i=0, length=arrayEvent.length;i+=1){

      if (arrayEvent[i] === fn){

        this._listeners[type].splice(i, 1);

        break;

         }

         }

      } else {

        delete this._listeners[type];

            }

        }

        return this;

    }

};

04、總結(jié)

學(xué)習(xí)這兩種模式,其實(shí)就是為了代碼解耦 ,讓每個(gè)獨(dú)立的對(duì)象分開(kāi)。需要從日常的業(yè)務(wù)場(chǎng)景去觀察,比如在分頁(yè)插件中,就可以利用“發(fā)布訂閱”為點(diǎn)擊每一個(gè)分頁(yè)數(shù)的時(shí)候觸發(fā)($emit)一個(gè)自定義事件,如果需要在點(diǎn)擊分頁(yè)的是做一些其他的時(shí)候,就可以在外面$on 這個(gè)事件,那么分頁(yè)插件就可以很好的封裝起來(lái),不用給里面?zhèn)鬟f參數(shù)或者回調(diào)函數(shù)之類(lèi)的了。


關(guān)注我們
值得信賴(lài)的IT教育機(jī)構(gòu)

值得信賴(lài)的IT培訓(xùn)機(jī)構(gòu)

成都校區(qū)地址:成都市武侯區(qū)孵化園9號(hào)樓A座2樓 西安校區(qū)地址:西安市未央?yún)^(qū)鳳城九路海博廣場(chǎng)B座 深圳校區(qū)地址:深圳市福田區(qū)彩田南路深圳青年大廈

蓉華教育,行勝于言,IT培訓(xùn)學(xué)??诒x擇

2016-2024 版權(quán)所有 ? 成都蓉華軟創(chuàng)科技有限公司官網(wǎng)(蜀ICP備20007585號(hào)-1 )

微信咨詢(xún)

微信咨詢(xún)

聯(lián)系電話

聯(lián)系方式

173-5852-6576