Vue2 跟 Vue3 的響應式數據(reactivity)原理筆記


Posted by m6fish on 2021-02-27

Photo by patrick le on Unsplash

資源

  • 共通
  1. 「面试题」20+Vue面试题整理
  • vue2
  1. Vue官網 2.x -Reactivity in Depth
  2. [掘竅] 為什麼畫面沒有隨資料更新 - Vue 響應式原理(Reactivity)
  3. [MDN] Object.defineProperty
  4. vue2 響應式原始碼
  • vue3
  1. Vue3 的 Proxy 能做到哪些精确的拦截操作?原理揭秘
  2. 一起來了解 Javascript 中的 Proxy 與 Reflect
  3. 你可以手寫Vue3的響應式原理嗎?
  4. vue3 響應式原始碼

主題

Vue2

vue初始化頁面時:

  1. Object.defineProperty重新設定data內的值(轉換成 getter / setter),
  2. 蒐集watcher(第一次get的時候紀錄watcher)
  3. set變動資料時,通知該對象底下所有 watcher觸發頁面重新渲染

注: 每個component都有各自的watcher
注: 因 Object.defineProperty,所以 vue2 不支持IE8以下

造成的問題

無法偵測到特定型態(Object, Array)的某些變動

  • Object 新增刪除屬性
// 官網範例
var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` is now reactive

vm.b = 2
// `vm.b` is NOT reactive

解法為使用 $set

Vue.set(vm.someObject, 'b', 2) 或者 this.$set(this.someObject, 'b', 2)

  • Array 內容或長度值的'直接'修改
var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // is NOT reactive
vm.items.length = 2 // is NOT reactive

解法為使用 $set 或者使用 Array.splice
這些Array方法可以被觀測到: push(), pop(), shift(), unshift(), splice(), sort(), reverse()


Vue3

Vue3 使用 ES6 proxy 代替 Object.defineProperty,proxy 可以直接代理 set行為,而且可以直接監聽到特定型態(Object, Array)的變動

  1. reactive() 建立響應式資料(使用 proxy)
  2. 頁面渲染過程中觸發getter, 蒐集依賴(track)
  3. 當資料變動 set時,觸發 tigger 找到關聯callback,更新頁面

Vue3響應式的流程圖
出自:(頁首資源7)你可以手寫Vue3的響應式原理嗎?

Proxy / Object.defineProperty 比較

  • Proxy 解決vue2原本特定狀況無法監聽到的問題
  • Proxy 相較於 Object.defineProperty 有更多新方法可以使用
  • Proxy 可以直接操作代理的物件,而 Object.defineProperty 需要歷遍整個物件修改
  • Proxy 即將成為新標準,效能會相對好些

總結

看看底層實作才了解到,原來以前vue2踩的渲染坑,是這樣出現的


#javascript #Vue







Related Posts

計畫列表

計畫列表

曾經的前端  library 霸主 :  jQuery

曾經的前端 library 霸主 : jQuery

React-[基礎篇]- React中的狀態state

React-[基礎篇]- React中的狀態state


Comments