[Hard] 📄 Two-way Data Binding
1. Please explain the underlying principle of how Vue2 and Vue3 each implement two-way binding
請解釋 Vue2 和 Vue3 各自如何實現雙向綁定的底層原理?
要理解 Vue 的雙向綁定,需要先明白響應式系統的運作機制,以及 Vue2 與 Vue3 在實作上的差異。
Vue2 的實作方式
Vue2 使用 Object.defineProperty 來實現雙向綁定,這個方法可以將一個物件的屬性包裝成 getter 和 setter,並且可以監聽物件屬性的變化。流程如下:
1. Data Hijacking(資料劫持)
在 Vue2 中,當一個元件中某個資料的物件被建立時,Vue 會遍歷整個物件中的所有屬性,並使用 Object.defineProperty 將這些屬性轉換成 getter 和 setter,這才使 Vue 可以追蹤資料的讀取和修改。
2. Dependency Collection(依賴收集)
每當元件中的渲染函式被執行時,會讀取 data 中的屬性,這時候就會觸發 getter,Vue 會記錄這些依賴,確保當資料變化時,能夠通知到依賴這些資料的元件。
3. Dispatching Updates(派發更新)
當資料被修改時,會觸發 setter,這時候 Vue 會通知到所有依賴這些資料的元件,並且重新執行渲染函式,更新 DOM。
Vue2 程式碼範例
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log(`get ${key}: ${val}`);
return val;
},
set: function reactiveSetter(newVal) {
console.log(`set ${key}: ${newVal}`);
val = newVal;
},
});
}
const data = { name: 'Pitt' };
defineReactive(data, 'name', data.name);
console.log(data.name); // 觸發 getter,印出 "get name: Pitt"
data.name = 'Vue2 Reactivity'; // 觸發 setter,印出 "set name: Vue2 Reactivity"