跟踪对象的变化

4

希望能够得到有关以下挑战的反馈/想法。

我一直在开发一个双向绑定库,已经接近完成,但留下了一个增强功能,并寻找最佳方法继续前进。

我正在使用基本的getter/setter跟踪对象(例如状态)的属性。当发生变化时,会执行相关例程以更新DOM。以下是极其简化的示例:

var state = {propertyA:1,propertyB:2,propertyC:3}
state.forEach((prop) => {
    Object.defineProperty(state, prop, {
        set: function (newValue) {
            value = newValue;
            // routines to update the DOM based on the changed state
        },
        get: function () {
            return value;
        },
        enumerable: true,
        configurable: true
    });
}

然而,在运行时,这个状态对象可能会收到新的属性。我想消除手动重新初始化所有属性的依赖性。
因此,我需要跟踪状态对象并为添加的属性添加必要的setter/getter。我尝试了以下方法,但是尽管将configurable设置为true,我也不被允许触及状态对象。
Object.defineProperty(window, 'state', {
    set: function (newValue) {
        value = newValue;
        // routine to apply setters/getters for the new properties
    },
    get: function () {
        return value;
    },
    enumerable: true,
    configurable: true
});

我真的希望能够避免像setInterval这样的超级麻烦的东西来检查对象更改。对于如何处理这种情况,有什么建议吗?


1
这是一个普遍存在的难题。那么数组呢?原始类型呢?像Angular、React和Vue这样的大型框架不依赖于事件来触发变化,而是选择使用一些差异算法(在Angular中,基于输入数据;在React和Vue中,基于生成的DOM)。 - Thomas
1个回答

4
你可以使用Proxy对象来简单地实现此操作。
对于MDN的文档

Proxy对象用于为基本操作(如属性查找、赋值、枚举、函数调用等)定义自定义行为。

let state = {
  propertyA: 1,
  propertyB: 2,
  propertyC: 3
}

function wrapObject(state) {
  const handler = {
    get: function(obj, prop) {
      console.log("get invoked for prop:: ", prop);
      return prop;
    },
    set: function(obj, prop, value) {
      console.log("set invoked for prop:: ", prop, " and value:: ", value);
      document.getElementById("root").innerHTML = `<div> prop: ${prop} value: ${value} </div>`;
      //Other code
    }
  };
  return new Proxy(state, handler);
}

state = wrapObject(state);
state.propertyA;
state.propertyD = 4;
//Update state by adding new property after 3 secs
setTimeout(() => {
  state.propertyE = 5;
}, 3000);
<div id="root"></div>


今天有很多支持,好建议! - Micha Schopman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接