在 Svelte 中,您可以使用 `array = array` 将数组标记为需要在视图中刷新吗?
In Svelte, you can use `array = array` to mark the array as needing a refresh in the view?
即使用
array = array;
触发视图刷新当前 array
?
例如下面使用
cards = [...cards, {name}];
到"add"数组cards
的一个条目,但是通过将cards
分配给一个新的数组,视图中的cards
将被刷新。
采样于:https://svelte.dev/repl/3ed20e7bac2e4b65944c98485d9217b3?version=3.18.1
(只需输入一些名称,下面的列表就会更新)。
然而,当输入 n
个名称时,这是 O(n²),因为每次创建一个新数组都是 O(n)。如果 (1) 用户希望一次输入几个或十几个名字,这不是什么大问题,或者 (2) 用户可能会输入一个名字几秒到 20 秒,那么任何延迟当条目多达 1000 或 2000 个名称时,UI 的 0.2 秒不是大问题。 (用户可能会更好地添加到服务器和数据库,以防万一停电。)
但如果我们不想要 O(n²) 时间,我们也可以使用:
cards.push({name});
cards = cards;
这将触发视图刷新。所以 Svelte 不做 "dirty checking"?是不是相对于Angular、Vue、React,他们是通过实际将数组转为字符串,检查数组是否发生变化来进行脏检查的?
示例:https://svelte.dev/repl/70cc3b08f6864ef387c691b8f126a7fd?version=3.18.1
没有行 cards = cards;
,列表将不会在视图中更新:
示例:https://svelte.dev/repl/25f41c51798d425e805fb4586a843363?version=3.18.1
所以 Svelte 并没有进行实际的脏检查,而是使用 cards = something;
作为提示 cards
已经改变,即使是 cards = cards
?那么,如果我们使用 array.push()
以便程序可以 运行 更快,那么我们是否可以将其用作通用技术来将某些内容标记为脏? Svelte 真的可以通过检测 cards.push()
语句来猜测 cards
已经改变吗?
更新:发现每个列表项加一个key,就不需要cards = cards
了,想知道为什么:
https://svelte.dev/repl/d78158ae54684bf28b8c2e9b527f1915?version=3.18.1
<ul>
{#each cards as card, i (i)}
<li>{card.name}</li>
{/each}
</ul>
您可以使用自定义商店来模拟 "detecting changes caused by push()
method"。
查看 Rich Harris 的 REPL
https://svelte.dev/repl/2699eb0fe7dd4621b3e585aec1a30d01?version=3.17.3
将变量赋值给自身是对编译器的提示,即视图的相关部分需要更新 — see here for more information。它旨在让您在性能需要时使用可变对象和数组,但会促使您使用不可变数据结构,因为这通常会导致更少的错误。
检测 array.push(...)
之类的东西并不实用 — 最好有一种单一、清晰的方式告诉编译器 'this has changed',而赋值运算符就是这种方式。
它与带密钥的每个块一起工作但不与未加密钥的块一起工作的原因实际上是由于错误 - 我提出了一个问题:https://github.com/sveltejs/svelte/issues/4373
即使用
array = array;
触发视图刷新当前 array
?
例如下面使用
cards = [...cards, {name}];
到"add"数组cards
的一个条目,但是通过将cards
分配给一个新的数组,视图中的cards
将被刷新。
采样于:https://svelte.dev/repl/3ed20e7bac2e4b65944c98485d9217b3?version=3.18.1
(只需输入一些名称,下面的列表就会更新)。
然而,当输入 n
个名称时,这是 O(n²),因为每次创建一个新数组都是 O(n)。如果 (1) 用户希望一次输入几个或十几个名字,这不是什么大问题,或者 (2) 用户可能会输入一个名字几秒到 20 秒,那么任何延迟当条目多达 1000 或 2000 个名称时,UI 的 0.2 秒不是大问题。 (用户可能会更好地添加到服务器和数据库,以防万一停电。)
但如果我们不想要 O(n²) 时间,我们也可以使用:
cards.push({name});
cards = cards;
这将触发视图刷新。所以 Svelte 不做 "dirty checking"?是不是相对于Angular、Vue、React,他们是通过实际将数组转为字符串,检查数组是否发生变化来进行脏检查的?
示例:https://svelte.dev/repl/70cc3b08f6864ef387c691b8f126a7fd?version=3.18.1
没有行 cards = cards;
,列表将不会在视图中更新:
示例:https://svelte.dev/repl/25f41c51798d425e805fb4586a843363?version=3.18.1
所以 Svelte 并没有进行实际的脏检查,而是使用 cards = something;
作为提示 cards
已经改变,即使是 cards = cards
?那么,如果我们使用 array.push()
以便程序可以 运行 更快,那么我们是否可以将其用作通用技术来将某些内容标记为脏? Svelte 真的可以通过检测 cards.push()
语句来猜测 cards
已经改变吗?
更新:发现每个列表项加一个key,就不需要cards = cards
了,想知道为什么:
https://svelte.dev/repl/d78158ae54684bf28b8c2e9b527f1915?version=3.18.1
<ul>
{#each cards as card, i (i)}
<li>{card.name}</li>
{/each}
</ul>
您可以使用自定义商店来模拟 "detecting changes caused by push()
method"。
查看 Rich Harris 的 REPL https://svelte.dev/repl/2699eb0fe7dd4621b3e585aec1a30d01?version=3.17.3
将变量赋值给自身是对编译器的提示,即视图的相关部分需要更新 — see here for more information。它旨在让您在性能需要时使用可变对象和数组,但会促使您使用不可变数据结构,因为这通常会导致更少的错误。
检测 array.push(...)
之类的东西并不实用 — 最好有一种单一、清晰的方式告诉编译器 'this has changed',而赋值运算符就是这种方式。
它与带密钥的每个块一起工作但不与未加密钥的块一起工作的原因实际上是由于错误 - 我提出了一个问题:https://github.com/sveltejs/svelte/issues/4373