Vue3 用 Proxy 实现响应式
Proxy 实现响应式
- 深度监听,性能更好
- 可监听 新增/删除属性
- 可监听数组变化
- 但,无法兼容所有浏览器,无法 polyfill
js
// 创建响应式
function reactive(target = {}) {
if (typeof target !== 'object' || target == null) {
// 不是对象或数组,则返回
return target;
}
// 代理配置
const proxyConf = {
get(target, key, receiver) {
// 改进
// 只处理本身(非原型的)属性
const ownKeys = Reflect.ownKeys(target);
if (ownKeys.includes(key)) {
console.log('get', key); // 监听
}
const result = Reflect.get(target, key, receiver);
// return result // 返回结果
// 深度监听,把上面修改成下面
return reactive(result);
// 那么性能是如何提升?
/**
* Object.defineProperty 一次性递归完
* Proxy 是 get 到哪一层,就递归到哪一层
*/
},
set(target, key, val, receiver) {
// 改进
// 重复的数据,不处理
if (val === target[key]) {
return true;
}
const ownKeys = Reflect.ownKeys(target);
if (ownKeys.includes(key)) {
console.log('已有的 key', key);
} else {
console.log('新增的 key', key);
}
const result = Reflect.set(target, key, val, receiver);
console.log('set', key, val);
console.log('result', result);
return result; // 是否设置成功
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key);
console.log('delete property', key);
console.log('result', result);
return result; // 是否删除成功
},
};
// 生成代理对象
const observed = new Proxy(target, proxyConf);
return observed;
}
// 测试数据
const data = {
name: 'zhangsan',
age: 20,
info: {
city: 'shenzhen',
a: {
b: {
c: {
d: {
e: 100,
},
},
},
},
},
};
const proxyData = reactive(data);
// 测试
console.log(proxyData.age);
// get age
// 20
// 没有深度监听
console.log(proxyData.info.city);
// get info
// shenzhen
// 深度监听
console.log(proxyData.info.city);
// get info
// get city
// shenzhen
// 新增的 key
console.log((proxyData.age1 = 100));
// 新增的 key age1
// set age1 100
// result true
// 100
那么性能是如何提升?
- Object.defineProperty 一次性递归完
- Proxy 是 get 到哪一层,就递归到哪一层