超淺談 Vue 的響應式原理

nchuuu
nchuuu
Nov 1 · 3 min read
Photo by Clément H on Unsplash

— Object.defineProperty, and some notes.

Vue 組件在初始化時會將 props, data…等屬性進行綁定,並監聽他們的變化,而後在該值對應的模板上執行渲染。比如:

其實 Vue 是利用了ES5標準下的 Object.defineProperty 來將 props, data… 轉變為響應式物件的。

Object.defineProperty(object, prop, descriptor)

其中 descriptor 的部分可以為 object 中的 prop 提供 get(getter), set(setter)的屬性方法,用於取值及賦值時的操作:

obj.a
// gotcha!
// 10
obj.a = 12;
obj.a
// gotcha!
// 13

以上是對範例中 obj 簡單操作的結果,透過 setter 及 getter 我們可以在取賦值時增加一些額外的操作。熟悉 Vue 開發的人應該也不難發現,這樣的操作其實跟 Vue 的 computed getter/setter 寫法是異曲同工的。


瞭解上述的方法後,就來看看 Vue 的原始碼中是如何將物件轉換成響應式對象的吧!我們可以從 GitHub 上找到 Vue,而相關檔案都會在 src/ 路徑底下。

首先來了解一下 Vue 程式的初始化流程,通常我們會在 index.js 中執行 new Vue() ,這個步驟藉由一個 Vue 的 Class 創建出 Vue 的 instance,並執行 this._init() 這個 Function。於 src/core/instance/index.js 中可以找到它:

_init 會處理 Vue 的生命週期、事件、data、props 等初始化的設定,相關原始碼在 src/core/instance/init.js 。其中將資料物件轉變為響應式的關鍵涵式為 initState() ,由 src/core/instance/state.js 中可以他執行了多個初始化的動作,包含 initProps initData initComputed 等等。

這次我們先專注initProps ,他在遍歷了所有的 props 後執行了涵式defineReactive ,下面節錄原始碼中比較重要的部分:

到了這裡,總算可以在 src/core/observer/index.js 中看到 defineReactive 實際使用了 Object.defineProperty 對傳入的參數進行 getter/setter 的設置:


探究原始碼的過程著實令人心累,且 vue 3.0 推出在即,但已趨成熟的 Vue 2真的很適合拿來研讀,在其中也能夠發現許多有趣的方法,以及恍然大悟的心情,甚至能夠讓自己寫 code 的能力加以提升!這次只關注在響應式的入門,有機會再來一一探索如 virtul dom 等核心的部分吧。

nchuuu

Written by

nchuuu

難為工程師

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade