v-forディレクティブは要素の移動を最小限に抑えるアルゴリズムを使用し、可能な限りその場で同じタイプの要素を再利用しようとする。
結論
→v-forは予期しないエラーが起こるので必ずユニークなkey属性と共に用いましょう。
この内容をプログラムで表したいと思います。
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<div id="app">
<ul>
<div v-for="fruit in fruits">
<p>{{fruit}}</p>
<input type="text">
</div>
</ul>
<button @click="remove">先頭を削除</button>
</div>
new Vue({
el: '#app',
data: {
fruits: ['りんご','バナナ','キィウイ']
},
methods:{
remove: function(){
this.fruits.shift()
}
}
})
問題点
インプットボックス内にそれぞれ上記を表す英語を入れて削除を実行すると
括弧内の表示が削除されずにずれます。
1.配列要素の'りんご','バナナ','キィウイ'についてはりんごが削除されて、りんごがバナナに置き換わり、バナナがキィウイに置き換わっている。
2.inputタグ内部は「可能な限り同じタイプ(inputタグ同士)の要素は再利用しようとする」でAppleが再利用され、Bananaが再利用されている。
この問題を解決する方法「Key」属性をあたえる
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<div id="app">
<ul>
<div v-for="fruit in fruits" v-bind:key="fruit">
<p>{{fruit}}</p>
<input type="text">
</div>
</ul>
<button @click="remove">先頭を削除</button>
</div>
or
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<div id="app">
<ul>
<div v-for="fruit in fruits" :key="fruit">
<p>{{fruit}}</p>
<input type="text">
</div>
</ul>
<button @click="remove">先頭を削除</button>
</div>
利用上での注意点
(1)indexは使用しない。なぜか?りんごが削除されたときにバナナのインデックスが「1」から「0」になるのでユニークな値ではないため。
(2)テンプレートタグでは使用しない。テンプレートタグは表示されない「pisplay: noneの適用」だけで残っているため削除には用いない。
(3)配列内でりんごが2回登場する場合はユニークとならないので、配列ではなくオブジェクトとしてオブジェクト.idをkeyに利用することを考える。