Contents
Vue のエラー
以下のコードは、下記のエラーとなります。
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
<template v-for="user in users" :key="user.id">
<user-row :user="user"></user-row>
</template>
</tbody>
</table>
<template> cannot be keyed. Place the key on real elements instead.
template に対して :key を設定していることによって当該エラーは発生しています。
タグを template ではなく div などに変更すればエラーも出ずに解決なのですが、レイアウトが崩れるという問題がある為、どうしても template が使用したい状況です。
そのような場合には template タグではなく、その配下のタグに対して :key を設定します。
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
<template v-for="user in users">
<user-row :user="user" :key="user.id"></user-row>
</template>
</tbody>
</table>
これでエラーは解消します。
:key は必要なのか?
余談ですが、:key を設定しなかったとしても、例えば Visual Studio Code だと下記メッセージが表示されるだけでエラーにはなりません。
Custom elements in iteration require 'v-bind:key' directives.
エラーにはなりませんが、axios などのHTTPクライアントで users を再度 get したとしても、更新されるのは data の users(user) だけで、コンポーネント側の props の user は変化しません。
key は必ず設定すべきです。
key 特別属性は、主に古いリストの代わりにノードの新しいリストを差分算出する VNode を識別するために Vue の仮想 DOM アルゴリズムに対するヒントとして使用されます。
キーがない場合、Vue は要素の移動を最小限に抑えるアルゴリズムを使用し、可能な限りその場で同じタイプの要素にパッチ適用/再利用しようとします。
キーがある場合は、キーの順序の変化に基づいて要素を並べ替え、そして、もはや存在しないキーを持つ要素は常に削除/破棄されます。
同じ共通の親を持つ子は、一意なキーを持っていなければなりません。重複するキーはエラーを描画する原因になります。
API | Vue.js