vuejs系列四-雙向綁定的實現

前言

做爲一名軟件開發人員,瞭解經常使用的設計模式應該算是咱們必備的技能之一了。若是你在編程中能夠駕輕就熟的使用這些,那你的代碼確定是知足了健壯性,可讀性,易維護的範疇以內的。本章咱們一塊兒來了解下前端開發中經常使用的設計模式發佈 訂閱。前端

發佈訂閱者模式是什麼

說道發佈訂閱者模式,那不得不提的就是觀察者模式,讓咱們先來對比下他們基礎特性(摘自維基百科):vue

  • 觀察者模式:在此種模式中,一個目標對象管理全部相依於它的觀察者對象,而且在它自己的狀態改變時主動發出通知。這一般透過呼叫各觀察者所提供的方法來實現。此種模式一般被用來實時事件處理系統。
  • 發佈訂閱者模式:在軟件架構中,發佈-訂閱是一種消息範式,消息的發送者(稱爲發佈者)不會將消息直接發送給特定的接收者(稱爲訂閱者)。

從他們對比的特徵中不難發現這二者有不少類似點:都是一對多的關係,(一個觀察者對象對應多個觀察者、一個發佈對應多個訂閱者。)都能實現數據的綁定。他們本質上的區別是發佈訂閱會引入Event Channel(訂閱器) 來將發佈的信息分發到訂閱者 (因此發佈訂閱能夠異 步處理訂閱的內容)。react

發佈訂閱者-vue中的雙向綁定

DOM ======> 數據 或 數據 ======> DOM *從圖中咱們能夠清楚的瞭解到 vue初始化時候會加載observer類,這個類是爲了 實現數據劫持,經過Object.propertyDefine爲其添加set和get屬性,而且將這些值添加到訂閱器中(deb)。

//實現observer數據劫持
export class Observer { 
    ...
    //遍歷全部屬性
    walk (obj: Object) {
      const keys = Object.keys(obj)
      for (let i = 0; i < keys.length; i++) {
        defineReactive(obj, keys[i])
      }
  }
}
//給屬性加上get set
export function defineReactive (
  ...
) {
   Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      ...
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      ...
      dep.notify()
    }
  })
}

//實現訂閱者
複製代碼
  • 咱們再來看看訂閱器中如何實現的,咱們訂閱器中須要的主要功能收集和發佈。 收集observer中劫持到到數據關聯對應的數據和訂閱者,通知對應的訂閱者訂閱到數據改變。
//實現訂閱器
export default class Dep {
   //收集
   addSub (sub: Watcher) {
    ...
  }
  //
  depend () {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }
  //通知
  notify () {
      ...
  }
}
複製代碼

*最後咱們來了解下訂閱者(watcher)接受到訂閱器到通知後所作到事情編程

export default class Watcher {
  // ...
  /**
   * Subscriber interface.
   * Will be called when a dependency changes.
   */
   // 還記得Dep.notify 調用到update
  update () {
    /* istanbul ignore else */
    if (this.lazy) {
      this.dirty = true
    } else if (this.sync) {
      this.run()
    } else {
      queueWatcher(this)
    }
  }

  /**
   * Scheduler job interface.
   * Will be called by the scheduler.
   */
   //這個方法並非實例化Watcher的時候執行的,而是監聽的變量變化的時候才執行的
  run () {
     ...
    }
  }
}
複製代碼

發佈訂閱的優缺點以及疑問

  • 優勢:發佈者和訂閱者是解耦的,符合了軟件設計高內聚,低耦合,只要引入訂閱發佈模式的事件中心,不管在何處均可以發佈訂閱。同時訂閱發佈者相互之間不影響。設計模式

  • 缺點:1.使用不當就會形成數據流混亂,致使代碼很差維護。2.訂閱發佈模式須要維護事件列隊,訂閱的事件越多,內存消耗越大bash

  • 在vue中數據改變如何通知視圖變化的?架構

    解析指令 ===> 數據劫持 ===> 觸發更新(經過watcher中的set)框架

  • 在vue到雙向綁定中訂閱器如何分發數據到對應到訂閱者?ui

總結

前期也寫過總結vue源碼的相關文章,那我爲什麼此時還要再寫一篇此類文章?由於隨着深刻對vue的使用,漸漸發現掌握vue雙向綁定的設計結構是如此重要,vue的此種設計不只能夠應用於軟件開發中的多種場景,並且是咱們熟練掌握vue這個開發框架的必經之路。this

相關文章
相關標籤/搜索