v-for に key 属性を指定するときとしないときの違いの一例

先日、v-forkey 属性を指定しないことが原因で生じる不具合に遭遇しました。別にたいしたものではなんですが、v-forkey 属性の確認を兼ねて簡単にまとめます。

ただ、2.2.0 以降のバージョンでは key は必須なんですね。

2.2.0 以降で、コンポーネントv-for を使用するとき、key は必須です

リストレンダリング #コンポーネントと v-for - Vue.js

雑なサンプルコードはこちら。

kntmr/playground - GitHub


v-forkey を指定しない状態でリストを描画する。で、リスト内のある要素をクリックするとスタイル (文字色とか) が変わるものとする。

<div>
  <ul>
    <li v-for="item in items">
      <p class="item" @click="select">{{ item.name }}</p>
    </li>
  </ul>
  <button @click="toggle">Toggle Data</button>
</div>

ここで、いずれかの要素をクリックしてスタイルを変更した状態で、リストの要素をすべて入れ替える。(サンプルコードの中ではボタンクリックで items の中身をすべて入れ替えるようにしてあります)

すると、リストの内容は書き変わるが、先ほど変更したスタイルがそのまま残る。これは v-forDOM を使い回しているため と思われる。

で、v-forkey を付ける。

<li v-for="item in items" :key="item.id">

こうすると、DOM の使い回しが回避できるため、あるべきスタイルで描画されるようになる。ちなみに、公式ガイドの key の項には以下のように記載されている。

この標準のモードは効率がいいです。しかしこれは、描画されたリストが子コンポーネントの状態や、一時的な DOM の状態に依存していないときにだけ適しています (例: フォームのインプットの値)。

リストレンダリング #key - Vue.js

というわけで、基本的には性能向上を目的として DOM を使い回す動作になっているようです。(が、安全な方に倒すのであれば、key を付けるのが無難な気がする...)