let app = new Vue({
data: {
text: "text",
text2: "text2"
}
})
第一步:
使用observe函數對Vue中的data對象進行處理,使其可觀察(observable)。這一步的實質就是使用Object.defineProperty方法重寫data的屬性,重寫屬性特征(主要指set和get兩個屬性特征函數,從而在獲取屬性值和設置屬性值的時候插入額外的操作來實現視圖中跟隨數據變化):
了解Vue實例化過程做了什么?下面可以看出,Vue實例化的時候,會把傳入對象的data屬性傳遞給實例的_data屬性,同時,調用observe函數來處理_data也就是option.data。observe函數實質上就是使_data對象的所有屬性的set, get。
class Vue {
constructor(options) {
this._data = options.data;
observe(this._data);
}
}
observe函數具體的實現,其實就是遍歷_data中的所有屬性,調用defineProperty在set和get來注入取值和設置值時的額外操作。
其中,dep是一個數組,其中存放着依賴於當前屬性的觀察者列表,也就是屬性改變時要通知列表中的這些對象來更新數據。
function observe(obj) {
Object.keys(obj).forEach((key) => {
defineReactive(obj, key, obj[key]);
})
}
// defineReactive函數
function defineReactive(obj, key, value) {
const dep = [];
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: () => {
// 讀取值時的額外操作,即綁定當前的觀察者到依賴列表中
dep.push(Dep.target);
return value;
},
set: (newVal) => {
if (newVal === value) { return };
// 設置值時的額外操作,即設置值時通知依賴列表中的所有觀察者來更新數據
dep.forEach((a) => a.update);
value = newVal;
}
})
}