为了账号安全,请及时绑定邮箱和手机立即绑定

Svelte 对每个块的键控的进一步解释

Svelte 对每个块的键控的进一步解释

慕的地6264312 2022-10-13 10:42:43
我不明白教程中的这一部分: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不起作用。感谢您的澄清。
查看完整描述

4 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

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

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

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


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

没有提供钥匙

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

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

提供 (thing.id) 密钥

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


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

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


查看完整回答
反对 回复 2022-10-13
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

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}

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


查看完整回答
反对 回复 2022-10-13
?
jeck猫

TA贡献1909条经验 获得超7个赞

我也在这个例子中苦苦挣扎,为什么图标没有改变。我注意到初始化 ( const emoji = emojis[name]) 之后在组件中计算的值保持不变,但是如果我们使用响应式声明:$: emoji = emojis[name];值将被重新计算,并且此示例可以正常工作。



查看完整回答
反对 回复 2022-10-13
?
守着一只汪

TA贡献1872条经验 获得超3个赞

有同样的疑问,然后我意识到“它将在块末尾添加和删除项目”可能意味着这里可能适用于 DOM,因此即使您在 JavaScript 中删除数组的第一项,Svelte 总是会删除最后一个DOM 节点。提供 key 后,DOM 和 JavaScript 都可以执行相同的操作。



查看完整回答
反对 回复 2022-10-13
  • 4 回答
  • 0 关注
  • 127 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信