ES6的Proxy代理多层结构数据 触发set方法的坑

ApiPost-宣博文 前端 2020-09-17

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.

Apipost 私有化火热进行中

评论