響應式系統(tǒng)
Vue.js是一款MVVM框架,數據模型僅僅是普通的JavaScript對象,但是對象的操作能影響視圖,其核心就是響應式系統(tǒng)。
Object.defineProperty
使用方法:
/*
obj: 目標對象
prop: 需要操作的目標對象的屬性名
descriptor: 描述符
return value 傳入對象
*/
Object.defineProperty(obj, prop, descriptor)
descriptor的一些屬性
- enumerable 屬性是否可以枚舉 默認false
- configurable 屬性是否可以被修改 默認false
- get 獲取屬性的方法
- set 設置屬性的方法
實現(xiàn)observe(可觀察的)
首先我們定義一個簡單的view函數峻厚,這個函數用來模擬視圖更新。
function view(val) {
// TODO 渲染視圖
console.log('視圖更新了');
}
Vue.js中源代碼是通過定義一個defineReactive方法對Object.defineProperty進行封裝了谆焊。
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get: function () {
return val;
},
set: function (newVal) {
if (val === newVal){
return;
}
val = newVal;
}
})
}
我們在上面在封裝一個observer惠桃,它可以對一個對象的所有屬性及子屬性都轉化為可偵測的。此處我們暫時只做第一層的偵測辖试,多層的偵測可以通過在defineReacticve中判斷typeof 為 object 時候繼續(xù)調用observer辜王,具體可以參考 object的變化偵測
function observer(value) {
if (!value || (typeof value !== 'object')) {
return;
}
Object.keys(value).forEach((key) => {
defineReactive(value, key, value[key]);
});
}
在 Vue 的構造函數中,對 options 的 data 進行處理罐孝,這里的 data 想必大家很熟悉呐馆,就是平時我們在寫 Vue 項目時組件中的 data 屬性(實際上是一個函數,這里當作一個對象來簡單處理)莲兢。
class Vue {
/* Vue構造類 */
constructor(options) {
this._data = options.data;
observer(this._data);
}
}
這樣我們只要 new 一個 Vue 對象汹来,就會將 data 中的數據進行「響應式」化续膳。如果我們對 data 的屬性進行下面的操作,就會觸發(fā) cb 方法更新視圖收班。
let o = new Vue({
data: {
test: "I am test."
}
});
o._data.test = "hello,world."; // 視圖更新了