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的属性将不能被枚举。