聚合物,在嵌套数组中添加新项,而不会被 dom-repeat 渲染

Polymer, adding new item in nested Array in not getting rendered by dom-repeat

提问人:Abhigyan Kumar 提问时间:1/24/2023 更新时间:4/4/2023 访问量:58

问:

我有一个嵌套数组,我需要为多个人添加新主题,但为了简单起见,我将仅向 Jon 添加新主题。

[
      {
        gender: "male",
        persons: [
          {
            name: "Jon",
            subjects: [
              { subName: "maths", marks: "45" },
              { subName: "phy", marks: "47" },
            ],
          },
        ],
      },
      {
        gender: "female",
        persons: [
          {
            name: "Amily",
            subjects: [{ subName: "bio", marks: "43" }],
          },
        ],
      },
    ]

我会在按钮点击时添加主题。

addSubject() {
    /* This doesn't work */
    let newData = [...this.data];
    newData[0].persons[0].subjects.push({ subName: "chem", marks: "50" });
    this.data = newData;
}

如果我使用,它可以工作,但如果我需要将主题添加到多个人,此方法每次都会更新属性。上面可以累积所有更改的临时数组,只更新一次。this.push("data.0.persons.0.subjects", { subName: "chem", marks: "50" });

呈现

<template is="dom-repeat" items="[[data]]">
  <div>Gender: [[item.gender]]</div>
  <template is="dom-repeat" items="[[item.persons]]">
    <div>Name: [[item.name]]</div>
    <template is="dom-repeat" items="[[item.subjects]]">
        <div>Subject: [[item.subName]], [[item.marks]]</div>
    </template>
  </template>
</template>

如果我尝试渲染更简单的数据,那么它可以正常工作

<template is="dom-repeat" items="[[simpleData]]">
   <div>Subject: [[item.subName]], [[item.marks]]</div>
</template>

static get properties() {
  return {
     simpleData: {
        type: Array,
        notify: true,
        value: () => [
          { subName: "math", marks: "11" },
          { subName: "phy", marks: "22" },
        ],
     },
}
addSubjectInSimple() {
    let newData = [...this.simpleData];
    newData.push({ subName: "chem", marks: "50" });
    this.simpleData = newData;
}

JavaScript 聚合物 Web 组件 聚合物-3.x DOM 重复

评论

0赞 G. Tranter 1/24/2023
尝试直接更新数据 - 而不是通过副本 - 。this.data[0].persons[0].subjects.push({ subName: "chem", marks: "50" }); this.data = [...this.data];
0赞 Danny '365CSI' Engelman 1/24/2023
仅供参考,聚合物几年前被宣布死亡。lit.dev 其继任者
0赞 Abhigyan Kumar 1/24/2023
@Danny'365CSI'Engelman 维护旧项目 🥺
0赞 Danny '365CSI' Engelman 1/24/2023
这意味着您正在学习旧技术,而不是新技术。我会换工作。Polymer 永远不会达到 Cobol 状态(开发人员现在制作 120K+)
0赞 Abhigyan Kumar 1/24/2023
@G.Tranter 这不是在更新 dom

答:

0赞 Tanner Stern 2/8/2023 #1

尝试在 dom-repeat 上添加 mutable-data 属性。这告诉聚合物在物体变化时随时注意深层变化。(您仍然需要调用或触发 dom 更新。this.setthis.notifyPath

Polymer 非常努力(有时太难了)在它认为不需要更新 dom 时更新 dom,这就是它对 s 进行脏检查的原因。在创建对象并更改对象时,您使用的是更现代的方法,现代浏览器通常可以处理,但 Polymer 需要“许可”才能使用该方法。dom-repeatnewData

注意:对象扩展是对对象进行浅层复制,而不是深度克隆。(有关更多信息,请参阅此答案...

评论

0赞 Abhigyan Kumar 2/10/2023
我需要同时添加到两者还是哪一个?另外,如果 top 在父组件中,而内部在子组件中,我是否需要使用 mixin 扩展父类和子类mutable-datadom-repeatdom-repeatPolymer.MutableData
0赞 Tanner Stern 2/10/2023
我真的不确定。我会尝试两种方式来查看,但我认为您至少需要它在顶层。这应该是直接观察您正在重新设置的对象。对不起,我不能更准确地说,即使在内部,我们通常也必须做很多摆弄才能让它正常工作。dom-repeat
0赞 Metal Paw 4/4/2023 #2

您应该能够对行执行以下操作: .this.data = newData;this.set("data", newData);

根据 Tanner Stern 的回应,它仍然可能无法更新,即您正在处理浅拷贝,因为它在技术上仍然是同一个对象,并且 Polymer 可能会将其视为未更新。您可以使用以下命令快速克隆阵列:let newData = JSON.parse(JSON.stringify(this.data));

这应该强制 Polymer 将整个数组设置为新值,并通知 dom 它已被更改。通常(根据我过去 5 年的个人经验),Polymer 不喜欢承认任何关于一个孩子访问的通知,例如。obj.obj但不是obj.obj.obj或更深,所以我发现最好的方法是使用 Polymer 函数设置整个数组/对象。set