回顾Vue2.x的Object.define Property
关于vue2的响应式实现可以看下我的另一篇文章:vue2响应式的实现一机Object.defineProperty的缺点
学习proxy语法
基本使用
javascript
const data = {
a: 1,
b: '20',
c: [1, 2, 3]
}
const proxyData = new Proxy(data, {
get(target, key, receiver) {
// 只处理本身(非原型)数据
if (Reflect.ownKeys(target)) {
console.log('keys', Reflect.ownKeys(target));
}
const result = Reflect.get(target, key, receiver);
console.log('get', key);
return result;
},
set(target, key, value, receiver) {
// 重复数据,不处理
const oldValue = target[key];
if (oldValue === value) {
return true;
}
console.log('set', key, value)
const result = Reflect.set(target, key, value, receiver);
return result;
},
deleteProperty(target, key) {
console.log('delete', key)
const result = Reflect.deleteProperty(target, key);
return result;
}
})
Reflect
- 和proxy能力一一对应
- 规范化、标准化、函数式
- 代替Object上的工具函数
实现响应式
Vue如何用proxy实现响应式
废话不多说,直接上代码
javascript
const data = {
a: 1,
b: '20',
c: {
d: {
e: [1, 2, 3]
}
},
info: {
name: 'wenrenfangge'
}
}
function reactive(target = {}) {
if (target == null || typeof target !== "object") {
return target;
}
const config = {
get(target, key, receiver) {
// 只处理本身(非原型)数据
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('已有的key:', key);
} else {
console.log('新增的key:', key);
}
const result = Reflect.get(target, key, receiver);
console.log('get', key);
return reactive(result);
},
set(target, key, value, receiver) {
// 重复数据,不处理
const oldValue = target[key];
if (oldValue === value) {
return true;
}
if (ownKeys.includes(key)) {
console.log('已有的key:', key);
} else {
console.log('新增的key:', key);
}
console.log('set', key, value)
const result = Reflect.set(target, key, value, receiver);
return result;
},
deleteProperty(target, key) {
console.log('delete', key)
const result = Reflect.deleteProperty(target, key);
return result;
}
}
return new Proxy(target, config);
}
const proxyData = reactive(data);
- 深度监听,性能更好
- 可监听新增/删除属性
- 可监听数组变化
Proxy能规避Object.defineProperty的问题,但是无法兼容所有浏览器,无法polyfill。