使用Proxy监听数据变化(自用)

26 阅读1分钟

该方法用来监听常规的复杂数据,尤其是针对后端接口返回的数据,因此不包含 Set、Map、Function 等特殊类型

该方法可以监听数据的属性修改、属性被删除、数组的变化等

function createDeepProxy(target, callback) {
      const proxyCache = new WeakMap();
      let rootProxy;

      const handler = {
        get(target, key, receiver) {
          const value = Reflect.get(target, key, receiver);

          // 递归代理嵌套对象/数组
          if (
            value &&
            typeof value === 'object' &&
            (Array.isArray(value) || value.constructor === Object)
          ) {
            if (!proxyCache.has(value)) {
              proxyCache.set(value, new Proxy(value, handler));
            }
            return proxyCache.get(value);
          }
          return value;
        },

        set(target, key, value, receiver) {
          const success = Reflect.set(target, key, value);
          if (success) callback(rootProxy);
          return success;
        },

        deleteProperty(target, key) {
          const success = Reflect.deleteProperty(target, key);
          if (success) callback(rootProxy);
          return success;
        },
      };

      // 验证初始数据类型
      if (!(target instanceof Object) && !Array.isArray(target)) {
        throw new Error('Only support Object and Array types');
      }

      // 创建根代理
      rootProxy = new Proxy(target, handler);
      return rootProxy;
    }

测试:

const data = {
  user: {
    name: 'John',
    hobbies: ['reading', 'coding'],
  },
  logs: [],
};

const proxy = createDeepProxy(data, (newData) => {
  console.log('Data changed:', JSON.stringify(newData));
});

proxy.user.age = 30; // 对象属性添加
proxy.user.hobbies.push('swimming'); // 数组操作
proxy.logs = [{ time: '2023', msg: 'test' }]; // 整个数组替换
proxy.logs[0].msg = 'updated'; // 嵌套对象修改
delete proxy.user.name; // 删除对象属性
Reflect.deleteProperty(proxy, 'logs'); // 删除对象属性