【问题标题】:Further explanation of Svelte's keyed each blockSvelte 对每个块的键控的进一步解释
【发布时间】:2020-10-11 10:10:16
【问题描述】:

教程中的这部分我没看懂:https://svelte.dev/tutorial/keyed-each-blocks

我可以看到things 数组已正确更新,因此正确的thing.color 按预期传递。但是通过第一句“默认情况下,当您修改 each 块的值时,它将在块末尾添加和删除项目,并更新任何已更改的值。”,似乎是在说Svelte 无论如何都会在点击按钮时移除最后一个块,那么剩下的 4 个块将面对切片的things,即

[{ id: 2, color: '#6a00a8' },
 { id: 3, color: '#b12a90' },
 { id: 4, color: '#e16462' },
 { id: 5, color: '#fca636' }]

并且由于initial被声明为const,它不能再被更新,所以thing.id 1--4的颜色仍然存在。

这是正确的理解吗?假设each 块是可交换的,这是默认行为吗?

然后它说使用thing.id 作为each 块的键将解决问题,即{#each things as thing (thing.id)}。我不明白如何在 each 块中使用密钥,如果未提供 thing.id,默认密钥是什么。以及为什么在提供thing.id 时默认密钥(如果有,或者默认无密钥)不起作用。

感谢您的澄清。

【问题讨论】:

    标签: javascript each svelte svelte-3


    【解决方案1】:

    我相信当您不提供密钥时,它会使用类似项目的索引作为默认值。这可以通过使用来验证

    {#each things as thing, index (index)}
        <Thing current={thing.color}/>
    {/each}
    

    这给出了与一开始不使用键相同的行为。


    我们将为id: 1 渲染的&lt;Thing&gt; 称为Thing1,依此类推。

    没有提供钥匙

    当我们从列表中删除第一项时,Thing1 仍然保持不变,因为与之关联的键(在本例中为索引)保持不变。之前发送到Thing2 的道具现在发送到Thing1。这发生在整个链条上。但现在少了一个元素,Thing5 已从 DOM 中移除。

    删除第一项时,与键“0”(Thing1)关联的组件Thing 的实例不会被销毁。发生这种情况是因为键保持不变(新数组在索引 0 处也有一个项目)。只有发送到Thing1 的道具发生了变化,initial 变量的颜色与原始项目的颜色相同,id: 1

    提供 (thing.id) 密钥

    当删除带有id: 1 的事物时,不存在任何映射到“1”的Thing 实例。因此,Thing1 已从 DOM 中删除。


    另一种理解方式是,当你给出一个键时,你实际上是在告诉 Svelte 将每个渲染块映射到那个键。当该键不再存在时,摆脱该块并将其从 DOM 中删除。但是如果 key 保持不变并且 props 发生变化,请更新 props 而不是重新创建块。

    当你不指定键时,它使用列表的索引作为键。因此,如果您从列表中删除项目,它不会重新创建或重新排序块,它只会更新道具。

    【讨论】:

    • 这是我见过的最好的解释。这应该去官方 Svelte 文档。
    【解决方案2】:

    API docs 是这样解释的:

    如果提供了一个键表达式——它必须唯一地标识每个列表项——Svelte 将在数据更改时使用它来区分列表,而不是在最后添加或删除项目。键可以是任何对象,但建议使用字符串和数字,因为它们允许标识在对象本身发生变化时保持不变。

    {#each items as item (item.id)}
      <li>{item.name} x {item.qty}</li>
    {/each}
    
    <!-- or with additional index value -->
    {#each items as item, i (item.id)}
      <li>{i + 1}: {item.name} x {item.qty}</li>
    {/each}
    

    我发现这在教程中也缺乏适当的解释。但是,我认为文档更清晰——可以为每个函数提供一个唯一的键,以便唯一地标识每次迭代。因此,当从 提供给每个函数的数据,可以识别和删除正确的迭代。

    【讨论】:

      【解决方案3】:

      有同样的疑问,然后我意识到“它将在块的末尾添加和删除项目”可能意味着这里可能适用于 DOM,所以即使你删除了 first 项目对于 JavaScript 中的数组,Svelte 总是删除 last DOM 节点。提供 key 后,DOM 和 JavaScript 都可以发挥相同的作用。

      【讨论】:

        猜你喜欢
        • 2021-09-28
        • 2022-01-24
        • 1970-01-01
        • 2013-05-15
        • 2021-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-09
        相关资源
        最近更新 更多