先說一下MVVM框架的一大特點,數據雙向綁定,它的實現總結一下有以下幾種方式:
- 髒檢查 (Angular)
- 數據劫持 (Vue)
- 發佈-訂閱
- 數據模型
而我們今天討論的Object.defineProperty屬於數據劫持的方式,數據劫持中還有和Proxy(代理)方法。這篇博客將簡單對比Vue3.0使用的Proxy,Object.defineProperty有哪些侷限性。
Object.keys(obj),將返回以obj對象所有的可枚舉屬性構成的數組。
Obeject.defineProperty實現雙向綁定的大概思路:
const data = {
name: ''
};
function say(name) {
if (name === '李誕') {
console.log('人間不值得');
} else if (name === '蔡康永') {
console.log('真正的貴族');
} else {
console.log('來看奇葩說');
}
}
// 遍歷對象,對其屬性值進行劫持
Object.keys(data).forEach(function(key) {
Object.defineProperty(data, key, {
enumerable: true,//可枚舉
configurable: true,//可改變
get: function() {
console.log('get');
},
set: function(newVal) {
// 當屬性值發生變化時我們可以進行額外操作
console.log(`大家好,我是${newVal}`);
say(newVal);
},
});
});
data.name = '蔡康永'; //真正的貴族
侷限一:
Object.defineProperty無法監聽數組的變化,所以vue在監聽數組的變化時有時不能做到雙向綁定。
而Vue中以下幾種數組的方法可以被監聽到變化:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
除此之外,數組的變化時監聽不到的,例如,vm.items[indexOfItem] = newValue;不會被監聽到的。
侷限二:
Object.defineProperty監聽的是對象的屬性,當監聽的對象有很多層級構成,則需要遞歸對象直至基本類型,才能進行監聽,比較麻煩。相比Proxy監聽整個對象的方式,就方便很多。
對比Object.defineProperty和Proxy兩種實現數據劫持方式的區別:
Object.defineProperty | proxy |
---|---|
監聽對象的屬性的變化 | 監聽整個對象 |
無法監聽屬性是數組的情況 | 可以監聽屬性是數組的情況 |