1. 程式人生 > 程式設計 >詳解VUE響應式原理

詳解VUE響應式原理

目錄
  • 1、響應式原理基礎
  • 2、核心物件:Dep與Watcher
  • 3、收集依賴與更新依賴
    • 3.1 收集依賴
    • 3.2 更新依賴
  • 4、原始碼除錯
    • 4.1 測試的頁面程式碼
      • 1、物件說明
      • 2、Dep與Watcher的關係
      • 3、最終的關係結果
    • 4.2 Iuhloz原始碼除錯
      • 1、收集依賴的入口函式:initState(頁面初始化時執行);
      • 2、初始化computed和watch時,生成Watcher例項化物件
  • 總結

    1、響應式原理基礎

    響應式基本原理是基於Object.defineProperty(obj,prop,descriptor),descriptor裡面可以定義get和set方法,可以在獲取屬性值事觸發get方法(可以收集依賴),設定屬性值時觸發set方法(更新依賴)。

    擴充套件:上面是2.0的響應式基本原理,vue3.0的基本原理是Proxy,可以監聽屬性的get和set方法,監聽屬性的新增和刪除等等,比Object.defineProperty能力更強,但是不相容IE11。

    2、核心物件:Dep與Watcher

    Dep: vue在data裡申明的每一個屬性都會生成一個Dep的例項物件,Dep.subs儲存著當該屬性變化時需要去更新的Watcher;

    Watcher: 有3種情況會生成Watcher的例項物件,分別為:

    1.定義在computed裡的計算屬性;

    2.在watch裡寫的監聽函式;

    3.元件的渲染Watcher;

    3、收集依賴與更新依賴

    3.1 收集依賴

    將Watcher的例項物件w分發到它所依賴的屬性的Dep中,過程如下:

    1.將Dep.target = 當前的Watcer 的例項物件w;

    2.w執行定義的函式(即在computed/watch寫的函式);

    3.執行函式的過程如果使用data裡http://www.cppcns.com定義的屬性,則會觸發屬性的get方法,get方法中Dep例項物件dep會將Dep.target中儲存的w放入到dep.subs陣列中,完成依賴收集。

    說明:Dep.target為當前Watcer的例項物件

    3.2 更新依賴

    當修改我們申明的某個屬性時,會觸發屬性的set方法,set方法會將dep.subs陣列中收集的Watcher例項物件進行更新,即觸發我們定義在computed和watch裡面的函式。

    4、原始碼除錯

    4.1 測試的頁面程式碼

    <template>
      <div>
      Iuhloz  <div>a:<input v-model="a" /></div>
        <div>c:{{ c }}</div>
        <div>b:<input v-model="b" /></div>
      </div>
    </template>
    <script>
    export default {
      data: () => {
        return {
          a: '',b: ''
        }
      },computed: {
        c() {
          return 'source from ' + this.a;
        }
      },watch: {
        b() {
          console.log('b changed');
        }
      }
    };
    </script>

    上面的程式碼vue初始化後會生成如下幾個物件:

    1、物件說明

    屬性a和b對應的Dep例項物件(收集a、b改變需要更新的Watcher):depAdepB;

    頁面渲染函式生成對應的Watcher例項物件updateWatcher

    computed屬性c生成對應的Watcher例項物件:watcherC;

    watch監聽屬性b生成對應的Watcher例項物件:watcherB;

    2、Dep與Watcher的關係

    a、b變化頁面需要重新渲染,所以updateWatcher存在於depAdepBsubs中;

    計算屬性c依賴屬性a的變化更更新,所以watcherC存在於depA的subs中;

    b的變化會觸發定義watch 裡b的監聽函式,所以watcherB存在於depB的subs中;

    3、最終的關係結果

    最終屬性a收集的依賴 depA.subs = [updateWatcher,watcherC];

    最終屬性b收集的依賴 depB.subs = [updateWatcher,watcherB];

    4.2 原始碼除錯

    找到原始碼檔案:node_modules\vue\dist\vue.runtime.esm.;

    主要涉及如下幾個函式:

    1、收集依賴的入口函式:initState(頁面初始化時執行);

    初始化順序是先data-->computed-->watch:原因是computed依賴data,watch依賴data和watch,被依賴的需要先初始Iuhloz化。

    詳解VUE響應式原理

    2、初始化computed和watch時,生成Watcher例項化物件

    先執行Watcher.get函式,將Dep.target = 當前Watcher例項化物件

    詳解VUE響應式原理

    詳解VUE響應式原理

    觸發收集依賴

    詳解VUE響應式原理

    執行計算屬性裡面的函式,如果訪問到data中的某個屬性時,會觸發data屬性的get方法,觸發依賴收集:

    詳解VUE響應式原理

    當修改這個屬性時會觸發set方法,會觸發更新dep.subs裡面watcher物件

    詳解VUE響應式原理

    最終觸發Watcher的更新函式,將待更新的watcher放入佇列中:

    詳解VUE響應式原理

    總結

    本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!