理解Vue深度響應原理

Vue核心原理之數據的深度響應

1.問題的引入

  • 爲何點擊下面的button界面會出現自增?segmentfault

    <div id="example-2">
    <simple-counter></simple-counter>
     </div>
     Vue.component('simple-counter', {
    template: '<button v-on:click="counter += 1">{{ counter }}
    </button>',
    data: function () {
      return { counter: 0 }
    }
     })
    new Vue({
        el: '#example-2'})
  • 爲何數據發生變化以後,視圖就發生變化?
  • 本文從三個方面來理解Vue處理深度響應的原理:
  • 數據定義
  • 數據綁定
  • 數據響應

2.數據的定義

  • 組件中定義數據{counter:0}
  • 初始化過程當中,會執行observe(data, this)
  • observe()過程當中會將data這個對象劫持,經過Object.definePropertydata上全部的屬性綁定上gettersetter函數;(這是針對對象,對於數組,Vue經過改寫數組的原生方法來劫持);
  • 通俗的說就是隻要誰獲取了counter的值就會觸發getter();要是誰改變了counter的值就會觸發setter();好比上述代碼中的button綁定{{count}}的時候必定會觸發getter();若是是count的值發生改變就必定會觸發setter()

3.數據綁定

  • 在頁面元素button中綁定{{count}};
  • 在編譯過程當中,針對這個button會產生一個Watcher(vm, exp, cb(newValue,oldValue)),vmVue對象,exp是數據綁定的數據;cb()的邏輯是用來更新頁面。如今的問題是如何將數據的變化和Watcher關聯起來。
  • 在這裏用到了一個重要的思想就是發佈訂閱模式Watcher初始化的時候會將Dep.target設置爲this,也就是Watcher本身,同時會觸發countgetter方法,getter裏面會調用Depdepend方法,depend方法會調用WatcheraddDep方法,addDep方法就是將Watcher本身存放在Dep的事件池裏面。數組

    class Dep {
      constructor() {
          this.id = uid++;
          this.subs = [];
      }
    
      addSub(sub) {
          this.subs.push(sub)
      }
    
      depend() {
          if (Dep.target) {
              Dep.target.addDep(this)
          }
      }
    
      removeSub(sub) {
         let ind = this.subs.findIndex(sub);
          this.subs.splice(ind, 1)
      }
    
      notify() {
          this.subs.forEach(sub => sub.update())
      }
    }
    Dep.target = null;

4.數據響應

  • 當發生點擊事件的時候,count的值改變,會觸發setter裏面的方法,這個方法會調用dep.notify();它會告知Dep的事件池裏的存放的Watcher去執行它的update()方法;Watcherupdate()方法;這個方法裏面會獲取count的新的值,給它的回調cb(),去更新視圖。
  • 這三個過程就是下面Vue官方給出的示意圖的含義。

clipboard.png

相關文章
相關標籤/搜索