Part 1 / Logic / Keyed each blocks
デフォルトでは、each
ブロックの値を変更すると、ブロックの 末尾 にアイテムを追加・削除し、変更された値を更新します。これはあなたが望むものではないかもしれません。
説明するより見ていただいたほうがわかりやすいしょう。'Remove first thing' ボタンを何度かクリックして、何が起きるか確認してください。先頭の <Thing>
コンポーネントは削除されず、末尾の DOM ノードが削除されます。そして残りの DOM ノードの name
の値は更新されますが、絵文字は更新されません。この絵文字は、Thing.svelte
が初期化されるときに固定されているのです。
代わりに、先頭の <Thing>
コンポーネントとその DOM ノードだけを削除して、残りには影響を与えないようにしたいと思います。
そのためには、each
ブロックに一意な識別子 (または"key") を指定します。
App.svelte
{#each things as thing (thing.id)}
<Thing name={thing.name}/>
{/each}
ここで、(thing.id)
は key であり、コンポーネントが更新されたときに変更するDOMノードを特定する方法を Svelte に伝えます。
Svelte は内部的に
Map
を使用しているので、どんなオブジェクトでもキーとして使用できます。つまり(thing.id)
の代わりに(thing)
を使うことができます。しかし、文字列または数値を使用する方が一般的に安全です。なぜなら、例えばAPIサーバーからの新しいデータで更新する場合に、参照が等しくなくても同一性が持続することを意味するからです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
import Thing from './Thing.svelte';
let things = [
{ id: 1, name: 'apple' },
{ id: 2, name: 'banana' },
{ id: 3, name: 'carrot' },
{ id: 4, name: 'doughnut' },
{ id: 5, name: 'egg' }
];
function handleClick() {
things = things.slice(1);
}
</script>
<button on:click={handleClick}>
Remove first thing
</button>
{#each things as thing}
<Thing name={thing.name} />
{/each}