进一步解释斯维尔特的键控每个块



我不理解教程中的这一部分: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.id1-4的颜色仍然存在。

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

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

谢谢你的澄清。

我相信当您不提供键时,它会使用类似于项的索引之类的东西作为默认值。这可以通过使用进行验证

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

这给出了与最初不使用密钥相同的行为。


让我们将为id: 1渲染的<Thing>称为Thing1,依此类推

没有提供钥匙

当我们从列表中删除第一个项目时,Thing1仍然保持不变,因为与它相关联的键(在本例中为索引)保持不变。先前发送到Thing2的道具现在被发送到CCD20。这种情况一直在发生。但是现在少了一个元素,Thing5就从DOM中删除了。

与密钥"CCD_ 22"相关联的组件CCD_;0";(Thing1)在移除第一个项目时不被销毁。发生这种情况是因为键保持不变(新数组在索引0处也有一个项)。只有发送到Thing1的道具发生了更改,使initial变量与id: 1原始项的颜色保持一致。

提供了(thing.id)密钥

当具有id: 1的事物被移除时,不存在映射到"0"的Thing的任何实例;1〃;。因此,Thing1被从DOM中移除。


另一种理解方式是,当你给出一个关键帧时,你实际上是在告诉Svelte将每个渲染块映射到该关键帧。当该键不存在时,去掉该块并将其从DOM中删除。但是,如果关键点保持不变,道具发生变化,则更新道具,而不是重新创建块。

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

API文档这样解释:

如果提供了一个密钥表达式——它必须唯一地标识每个列表项——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}

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

我也很难理解这个例子,为什么图标没有改变。我注意到初始化后在组件中计算的值(const emoji = emojis[name])保持不变,但如果我们使用反应声明:$: emoji = emojis[name];值将被重新计算,这个例子运行良好。

有同样的怀疑,然后我意识到什么"它将在块"的末尾添加和删除项目;这可能意味着这里可能适用于DOM,因此即使在JavaScript中删除数组的第一个项,Svelte也总是删除最后一个DOM节点。通过提供密钥,DOM和JavaScript都可以执行相同的操作。

无论何时在{#each} {/each}中使用嵌套组件,如果存在多个组件,svelte都需要一种单独识别每个组件的方法。它通过在内部为它们分配一个键来实现这一点。如果要操作这些组件,可以显式地为它们指定关键帧,以便识别它们。

那里发生的事情是,由于没有明确定义键,它计算"事物"的大小并显示它们。每当您减小"things"的大小时,它会再次从顶部重申为"things的大小",而不是选择相应的<Thing>,因为您没有绑定它们。您需要将<Thing>与'things'元素中的东西绑定,以便可以根据'things'元素的值进行操作。

在该示例中,使用CCD_ 36作为密钥进行识别。你也可以使用类似(thing.hashCode())的东西,结果会是一样的。任何导致唯一标识并绑定到"事物"的东西都可以。

相关内容

  • 没有找到相关文章

最新更新