我有一个用于游戏编辑器的60x30网格,随着单元的更新,将创建一个新数组来保存状态。
问题在于,当我更新该网格数组时,这会更改属性,并导致render()
重新创建网格。这似乎几乎是显而易见的,但是那我的选择变成了什么?
如果这过于具体,请想象只是一个巨大的项目列表,并且您有一个不变的数组,其中的一项属性必须更改。
render() {
return html`
${this.data?.cells.map((row) => {
return row.map((cell) => {
return html`<editor-cell .data="${cell}"></editor-cell>`;
});
})}
`;
}
巧合的是,我在Angular上遇到了同样的问题,因为它只有一个trackBy
使用for循环,而{{1}}使用了index或item.id来防止重新生成项目列表。我只是为此接受了独角兽,但这是同样的问题。
问题:
我在这里对不可变状态缺少什么?我完全理解为什么会发生这种情况,它是一个新数组,所以点亮的元素只会呈现它认为是新数组的内容。我想要那个,但是一旦渲染了网格,我就不理解渲染和数据更新之间的分离。我或者缺少对生命周期的关键理解,或者我的状态处理方法完全是错误的。
答案 0 :(得分:0)
如果您更新了整个数组,则会更改内存引用,然后lit-html必须重新渲染整个数组,因为它不知道哪些项会更改。
在lit-html文档中,您可以找到有关Repeating templates的内容,对此进行了很好的解释。
在这种情况下,您应该使用repeat
指令,该指令可根据用户提供的键对列表进行有效的更新:
render() {
return html`
${repeat(this.data?.cells, row => row.id,
row => html`${repeat(row, cell => cell.id,
cell => html`<editor-cell .data="${cell}"></editor-cell>`
)}`
)}
`;
}
请注意第二个参数的重要性,它是每个项目保证的唯一键。