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


    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.

  • 相关阅读:
    外部排序分析
    C++读写CSV文件
    springMVC之annotation优化
    用Scertify Professional实现代码审查
    flash与字符串:字符串与属性
    题目描述:字符串查找
    matlab遗传算法
    开发传感器应用
    Java 高效 MVC & REST 开发框架 JessMA v3.2.1 即将发布
    基于drools创建自己的关系操作符
  • 原文地址:https://www.cnblogs.com/phpwechat/p/14764021.html
Copyright © 2020-2023  润新知