Proxy實現觀察者模式(vue3.0)
vue3.0之前通過Object.defineProperty數據劫持來實現數據監聽,vue3.0即將引入Proxy來實現。
//添加觀察者
const queuedObservers = new Set();
const observe = fn => queuedObservers.add(fn);
//創建proxy代理
const observable = obj => {
for(const [key, value] of Object.entries(obj)) {
if (value instanceof Object) {
obj[key] = observable(obj[key])
}
}
return new Proxy(obj, {
set: (target, key, value, receiver) => {
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(observer => observer());
return result;
}
})
};
//被觀察的 對象
const person = observable({
name: '張三',
age: 20,
s: {
a: { d: 1 }
},
a: { s: 1}
});
function print() {
console.log(`${person.name}, ${person.age}`)
}
function print2() {
console.log(`我是二號觀察者:${person.name}, ${person.age}`)
}
//添加觀察者
observe(print);
observe(print2);
person.s.a.d = 2;
談談Object.defineProperty的缺點:
- 不能監聽數組變化
- 必須遍歷對象每個屬性
- 同理深度遍歷爲對象的屬性
Object.defineProperty監聽的目標是對象屬性,proxy目標是對象,也就省去了屬性的遍歷,然而免不了深度監聽爲對象的屬性。
Object.defineProperty的一些描述符屬性:
- configurable爲false時候,對象屬性將不能被delete,並且在嚴格模式下會跑出錯誤
Object.defineProperty(person, 'name', {
configurable: false,
value: 'John'
})
- Writable爲fasle,將不能被直接修改,可以通過defineProperty修改;
- Enumerable爲false的屬性將不能被枚舉。