Always Provide a :key
v-for — Rendering Lists
v-for iterates arrays, objects, or numeric ranges. The :key prop makes Vue's diffing fast and predictable.
What you'll learn
- Iterate an array with v-for
- Iterate object keys
- Always set :key
v-for renders one node per item in a list. Pair it with a stable :key and Vue can patch the DOM in place instead of recreating it.
Arrays
<script setup lang="ts">
import { ref } from 'vue'
const items = ref([
{ id: 1, name: 'Pen' },
{ id: 2, name: 'Notebook' },
])
</script>
<template>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</template> You can also receive the index as a second argument:
<li v-for="(item, i) in items" :key="item.id">
{{ i + 1 }}. {{ item.name }}
</li> Objects and Ranges
Objects yield value, key, and index:
<li v-for="(value, key, i) in profile" :key="key">
{{ i }}. {{ key }}: {{ value }}
</li> A number iterates from 1 to N inclusive:
<span v-for="n in 5" :key="n">{{ n }}</span> Keys Matter
Always use a stable, unique key per item. Using the array index as a key looks fine until you insert, remove, or reorder rows: form input values bleed between rows, animations glitch, and child component state attaches to the wrong item.
// good: id is stable
:key="item.id"
// bad: index changes when the list reorders
:key="i" Skip v-for + v-if on the same element. Instead, filter with a computed and iterate the result.
v-model — Two-Way Binding →