Everywhere (vueschool, in the official docs, here, here, here etc.) it is recommend to use a unique key for each item in an array when using v-for
in vue, to quote the official docs and another answer:
To give Vue a hint so that it can track each node's identity, and thus reuse and reorder existing elements, you need to provide a unique key attribute for each item:
I'm working with a large data-table, where we have around 200 rows with ~5 columns being displayed and updated through pagination. I'm, like everywhere told, using a key
for each row with the id
being the unique key for each item. Each pagination takes a lot of time (around 1s) due to every component being re-mounted which seems to be the expected behavior when the key changes?
Example:
// App.vue
<template>
<button @click="heros.splice(0, heros.length, ...moreHeros)">Change list</button>
<button @click="heros.push({name: `Ivy ${count++}`})">Add hero</button>
<button @click="heros.pop()">Remove hero</button>
<ul>
<SuperHero v-for="(hero, index) in heros" :name="hero.name" :key="index"/>
</ul>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import SuperHero from './SuperHero.vue';
const moreHeros = [
{name: 'Superman'},
{name: 'Spiderman'}
];
const count = ref(0);
const heros = reactive([
{name: 'Batman'},
{name: 'Robin'},
]);
</script>
// SuperHero.vue
<template>
<li>
<strong>Name:</strong> {{ name }}
</li>
</template>
<script lang="ts" setup>
import { onMounted } from 'vue';
defineProps<{
name: string;
}>();
onMounted(() => console.log('Mounted'));
</script>
If we now replace the list, all items are updated but each one re-mounted because the key changed.
But if we now use index
like so:
<ul>
<SuperHero v-for="(hero, index) in heros" :name="hero.name" :key="index"/>
</ul>
The list is updated as well (through props) plus we get the performance benefit of vue not re-mounting the other components. If we remove an item the key simply doesn't exist anymore so vue un-mounts the component, same for when a new item is added where a new key is introduced.
This doesn't make that much difference in most cases, but the re-rendering part causes major performance issues if you render a large list with 5000 plus components in it where on, page change, the id for every row changes causing vue to un-mount and re-create every single component.
My argument is, all the arguments given here, here and other places to support the usage of key
are based on examples where, simply put, reactivity is circumvented by not using ref
, watch
or any other method - which is a bug and not something that should be fixed by simply re-rendering the whole component.
Why is it still recommended, everywhere, that you should use a unique key
instead of index
and just make use of reactivity in a proper way? Vue should only mount/un-mount a component if an item is added / removed because in any other cases, just the props for the given component changes which does not need a re-mount.
Playground with example, notice that when using hero.name
as key, the component is re-mounted, but when using index
just patched. In botch cases it works as expected.
heros
instead ofusers
sinceusers
doesn't exist in your question's code snippet which I figure was a typo. Regardless, will probably need to see more code to fully understand the issue – Decurionkey
and what it's for... – Bensky