其原理:在Vue中其實就是通過Object.defineProperty來劫持對象屬性的setter和getter操作,并“種下”一個監(jiān)聽器,當(dāng)數(shù)據(jù)發(fā)生變化的時候發(fā)出通知。
那我們先來了解一下Object.defineProperty:
語法
Object.defineProperty(obj,target,texing)參數(shù)說明:
obj:-操作的對象
target:需定義或修改的屬性的名字
texing:目標(biāo)屬性所擁有的特性可供定義的特性列表
value:屬性的值
writable:如果為false,屬性的值就不能被重寫。
configurable: 如果為false,則任何嘗試刪除目標(biāo)屬性或修改屬性性以下特性(writable, configurable, enumerable)的行為將被無效化。
enumerable: 是否能在for...in循環(huán)中遍歷出來或在Object.keys中列舉出來。
set:一旦目標(biāo)屬性被賦值,就會調(diào)回此方法。
get: 一旦目標(biāo)屬性被訪問就會調(diào)回此方法,并將此方法的運算結(jié)果返回用戶。
注:當(dāng)使用了getter或setter方法,不允許使用writable和value這兩個屬性
舉個栗子(數(shù)據(jù)劫持):
// 劫持
function hijack(data) {
if (!data || typeof data !== 'object') {
return;
}
// 拿到對象里的每個key 和 value
Object.keys(data).forEach(item => {
// item:key data[item]:value
defineProperty(data, item, data[item]);
});
}
function defineProperty(obj, key, value) {
// 如果value是個對象則調(diào)用 hijack重新遍歷(對象嵌套對象)
hijack(value);
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function () {
console.log('只要訪問了該屬性,我就會執(zhí)行');
return value;
},
set: function (newValue) {
if (value === newValue) {
return
}
console.log('更新了!', value + '->' + newValue);
value = newValue;
}
});
}
var obj = {
a: 1,
b: 2
}
hijack(obj);
這個是控制臺的結(jié)果:

image.png