When using v-for
, it is strongly recommended to include a key
. Furthermore, as explained here, using the array index as your key doesn't really help.
If your elements have an id
property, then that's great - you could just use that as your key. But what about when your elements don't have an id
property? What should you use as your key in that scenario?
A better solution would be to use an external library to generate a hashcode from the value of your object and use that as an id. i.e. object-hash
An example using object-hash
const hash = objectHash; // this should be the import i.e. require('object-hash');
new Vue({
el: '#app',
template: `
<div>
<p v-for="item in itemsWithHash" :key="item.key">
{{item.name}} {{item.lastname}}<br>key: {{ item.key }}
</p>
</div>
`,
data: () => ({
items: [
{ name: 'john', lastname: 'doe' },
{ name: 'bob', lastname: 'smith' },
{ name: 'alice', lastname: 'james' }
]
}),
computed: {
itemsWithHash() {
return this.items.map(i => ({ ...i, key: hash(i) }));
}
}
});
<script src="https://cdn.jsdelivr.net/npm/object-hash@1.3.1/dist/object_hash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
You can use the index
of the iteration as a key, but keep in mind that this will not trigger changes on the view if you update the item by index. (Vue uses the key to detect changes, so it wont re-render the template if the key is not updated)
<div v-for="(item, i) in items" :key="i">
// some content.
</div>
Note the example below where mutating the items directly by index does not update the view but prints the change to the console:
new Vue({
el: '#app',
template: `
<div>
<p v-for="(item, index) in items" :key="index">
{{item.name}} {{item.lastname}}<br>index: {{ index }}
<button @click="changeForMary(index)"> Replace with Mary Smith</button>
</p>
</div>
`,
data: () => ({
items: [
{ name: 'john', lastname: 'doe' },
{ name: 'bob', lastname: 'smith' },
{ name: 'alice', lastname: 'james' }
]
}),
methods: {
changeForMary(index){
this.items[index] = { name: 'mary', lastname: 'smith' };
console.log(`index ${index} changed to ${JSON.stringify(this.items[index], null, '\t')}`);
}
}
});
<script src="https://cdn.jsdelivr.net/npm/object-hash@1.3.1/dist/object_hash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>