简体   繁体   English

如何强制更新子组件?

[英]How to force an update of a subcomponent?

Lit Documentation says:点燃的文档说:

When called with no arguments, requestUpdate() schedules an update, without calling a hasChanged() function.当在没有 arguments 的情况下调用时, requestUpdate()会安排更新,而不调用 hasChanged hasChanged() function。 But note that requestUpdate() only causes the current component to update.但请注意requestUpdate()只会导致当前组件更新。 That is, if a component uses the code shown above, and the component passes this.myArray to a subcomponent, the subcomponent will detect that the array reference hasn't changed, so it won't update.也就是说,如果一个组件使用上面显示的代码,并且该组件将this.myArray传递给一个子组件,则该子组件会检测到数组引用没有改变,因此它不会更新。

So how to force an update of a subcomponent (even if the subcomponent's attribute doesn't change)?那么如何强制更新子组件(即使子组件的属性没有改变)?

render() {
  return html`
    <ul>
      ${this.myArray.map(
        (item) => html`
          <li>
            ${item.text}
            <my-subcomponent foo="${item.bar}"></my-subcomponent>
          </li>
        `
      )}
    </ul>
  `;
}

Edit: Repro in Lit Playground编辑: 灯光游乐场中的重现

创建this.myArray的克隆以强制子组件重新渲染

 this.myArray = [...this.myArray]

Thank you for the lit.dev playground repro, I was able to identify some issues that should resolve your issue.感谢您提供 lit.dev 游乐场重现,我能够确定一些应该解决您的问题的问题。

Before jumping into the various fixes, why is the subcomponent not re-rendering?在进行各种修复之前,为什么不重新渲染子组件? LitElements render as a function of their properties & state. LitElements 呈现为 function 和 state。 If properties don't change, they don't re-render.如果属性没有改变,它们就不会重新渲染。

The subcomponent has two reactive properties, myArray and id .子组件有两个反应属性, myArrayid myArray is only set once on construction from localstorage and never updated - so it will never trigger an update. myArray仅在从 localstorage 构造时设置一次并且从不更新 - 所以它永远不会触发更新。 The id number also never changes for a given subcomponent so will never trigger an update.给定子组件的id编号也永远不会更改,因此永远不会触发更新。 Because neither properties change, the subcomponent doesn't re-render.因为两个属性都没有改变,所以子组件不会重新渲染。

Option 1: Pass the new array to the sub-component.选项 1:将新数组传递给子组件。

Fix 1 in Lit Playground 修复 1 照明游乐场

The only change I've made is to pass myArray to sub-component explicitly, (note .myArray=${this.myArray} ):我所做的唯一更改是将myArray显式传递给sub-component (注意.myArray=${this.myArray} ):

<li>${item.text} (<sub-component id=${item.id}.myArray=${this.myArray}></sub-component>)</li>

This works because now when the parent updates this.myArray , the parent passes this new array to the sub-component.这是有效的,因为现在当父级更新this.myArray时,父级将这个新数组传递给子组件。 The sub-component then notices that the reactive property myArray has changed and a render is scheduled.然后,子组件会注意到反应属性myArray已更改并安排了渲染。

Option 2: Only pass the item to the sub-component选项2:仅将项目传递给子组件

This is a larger change, but more maintainable and simpler.这是一个更大的变化,但更易于维护和更简单。 Instead of passing both the array and item id to each sub-component, only pass the item that the sub-component cares about.与其将数组和item id都传递给每个子组件,不如只传递子组件关心的item。

This does less work on the sub-component because each sub-component doesn't need to loop through the whole array to find the element that it cares about.这对子组件所做的工作较少,因为每个子组件不需要遍历整个数组来查找它关心的元素。

Working fixed playground from repro . 从 repro 工作的固定操场

This approach requires a change in changeMyArray .这种方法需要更改changeMyArray Instead of mutating the items, new items need to be returned.不是改变项目,而是需要返回新项目。

  changeMyArray() {
    this.myArray = this.myArray.map(
      (item) => {
        return {...item, colored: !item.colored};
      }
    );
  }

Breaking down that example.分解那个例子。 this.myArray.map already returns a new array so the array spread is not required. this.myArray.map已经返回一个新数组,因此不需要数组扩展。 Within the map each item that is modified must return a new object.map中,每个被修改的项目都必须返回一个新的 object。 This is similar to how redux works and the linked article may provide more helpful details.这类似于redux 的工作方式,链接的文章可能会提供更多有用的详细信息。

Now the parent render function can be updated to pass the item directly to the subcomponent with: <li>${item.text} (<sub-component.item=${item}></sub-component>)</li> .现在可以更新父渲染 function 以将项目直接传递给子组件: <li>${item.text} (<sub-component.item=${item}></sub-component>)</li>

Now when the item changes, the sub-component automatically re-renders.现在,当item更改时,子组件会自动重新渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM