Help us understand the problem. What is going on with this article?

Vue.js: v-forのkeyをindex以外に設定する必要がある理由について

Vue.jsの公式(key API ドキュメント, スタイルガイド)を確認しても分かりづらいので投稿します。

keyを設定しないと

あるissueに対するcontributorのコメントに下記のようにあります。

You are using the index as the key... which is the same as no key at all. You should give each of your data objects a unique id so that they can be keyed properly.

意訳)
keyにindexを使用していますね...それは、keyを設定していないのと同じです。
一意のidをkeyに設定してください。

つまり、keyを設定しないと配列のindexがデフォルトで使用されるようです。

アニメーション問題

ここから本題です。

keyを未設定もしくは、indexを設定すると、Vue.js: v-forで項目インデックスをkey属性にしていいのかに記載されているような問題が生じます。(子コンポーネントも想定通りにならないことがあります。)

この問題はあるissueにおけるcontributorのコメントによって理解できます。

example, let's say the first item in the array is removed. if you use an index, Vue will assume the last element was removed and update every remaining element as it shifts everything down

keyにindexを設定してある状態で、配列の先頭を削除したとしましょう。
Vueは、最後の要素が削除され、残りの要素が更新された(shift down)とみなします。

この内容も踏まえ考えると、VDOMのデータ参照は下記のまま変更されず

<!-- v-forのkeyを指定しなかった場合、デフォルトでindexが割り振られる -->
<DOM1></DOM> <!-- 参照key: itemsの1 -->
<DOM2></DOM> <!-- 参照key: itemsの2 -->
<DOM3></DOM> <!-- 参照key: itemsの3 -->
<DOM4></DOM> <!-- 参照key: itemsの4 -->
data: {
 items: [
  'リスト1', // key = index (1)
  'リスト2', // key = index (2)
  'リスト3', // key = index (3)
  'リスト4'  // key = index (4)
 ]
}
//先頭のデータが削除される
data: {
 items: [
  'リスト2',  // key = index (1)
  'リスト3',  // key = index (2)
  'リスト4'   // key = index (3)
 ]
}

VDOM側からすると、下記の認識になると思われます。
VDOM1~VDOM3は、データの変更
VDOM4だけitemsの4がないので要素の削除(アニメーション)

データの変更は無事行われているので、見た目上、先頭の要素がトルツメされたように見えます。パフォーマンスも良いようです。

これらを防ぐためにkeyに一意となる値を設定する必要があると思われます。

keyに一意となる値を設定したら

念のため、keyに一意となる値を設定した場合のイメージを記載しておきます。

<!-- v-forのkeyをに一意となる値を設定 -->
<DOM1></DOM> <!-- 参照key: hoge1 -->
<DOM2></DOM> <!-- 参照key: hoge2 -->
<DOM3></DOM> <!-- 参照key: hoge3 -->
<DOM4></DOM> <!-- 参照key: hoge4 -->
data: {
 items: [
  'リスト1', // hoge1
  'リスト2', // hoge2
  'リスト3', // hoge3
  'リスト4'  // hoge4
 ]
}
//先頭のデータが削除される
data: {
 items: [
  'リスト2',  // hoge2
  'リスト3',  // hoge3
  'リスト4'   // hoge4
 ]
}

keyがindexでも問題ない場合

リスト表示するだけなら特に問題は生じないはず。
リストの削除時にアニメーションする場合や、子コンポーネントをもつ場合、表示が意図通りにならないようです。
その場合は、コンポーネントにkeyを与えることで対処できることもあります。

kudo_kk
フロントエンドエンジニア
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away