Proxy代理多层结构Demo
//需要被代理的数据
var data=[
{name:"小明",age:12},{name:"小红",age:15},{name:"小蓝",age:17}
];
//代理后的数据对象 操作proxyData会影响data数据,但直接更改data不会触发get和set方法
const proxyData=new Proxy(data,{
get(obj, index) {
return obj[index];
},
set: function (target, key, value) {
target[key] = value;
return true;
});
假设给proxyData[0]["name"]="小明_修改后" 不会触发proxyData的set方法,因为proxyData[0]对象的指向没有变。
目前我解决的方法是:在赋值的时候
let obj=proxyData[0];
obj["name"]="小明_修改后";
proxyData[0]=obj;
这种方法可以修改proxyData[0]对象的指向obj,从而触发set方法,但这种方法有一定局限性,当我们的数据有更多未知层的时候修改内层数据还是无法触发set方法。
然后在原来基础加一个递归,通过递归触发set
function deepProxy(obj, cb) {
if (typeof obj === 'object') {
for (let key in obj) {
if (typeof obj[key] === 'object') {
obj[key] = deepProxy(obj[key], cb);
}
}
}
return new Proxy(obj, {
/**
* @param {Object, Array} target 设置值的对象
* @param {String} key 属性
* @param {any} value 值
* @param {Object} receiver this
*/
set: function (target, key, value, receiver) {
if (typeof value === 'object') {
value = deepProxy(value, cb);
}
let cbType = target[key] == undefined ? 'create' : 'modify';
//排除数组修改length回调
if (!(Array.isArray(target) && key === 'length')) {
cb(cbType, { target, key, value });
}
return Reflect.set(target, key, value, receiver);
},
deleteProperty(target, key) {
cb('delete', { target, key });
return Reflect.deleteProperty(target, key);
}
});
}
// 数组测试
let a = deepProxy([], (type, data) => {
console.log(type, data);
});
a.push(1)
a.push({ a: 1 })
// 对象测试
let b = deepProxy({}, (type, data) => {
console.log(type, data);
});
b.name = '大花猫花大';
b.info = {
age: 10,
data: {
data: {
data: {
text: 1
}
}
}
}
delete b.info.age;
另外如果在"use strict"严格模式下,set方法需要返回true.