Vue v-for
The v-for directive repeats a template block once for every item in an array, object, or range, making it the standard way to render lists in Vue.
The v-for Directive
v-for uses a special syntax in the form item in items, where items is the source array from your data and item is an alias for the element currently being iterated. Vue renders the element it's attached to once per entry in the array, in order, and keeps the DOM in sync whenever the array changes.
Basic v-for over an array
<div id="app">
<ul>
<li v-for="fruit in fruits" :key="fruit">
{{ fruit }}
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return {
fruits: ['Apple', 'Banana', 'Cherry', 'Dragon fruit']
}
}
})
app.mount('#app')
</script>Why Every v-for Needs a :key
Vue reuses and reorders existing DOM nodes for performance instead of rebuilding the whole list from scratch. The :key attribute gives each node a stable identity so Vue can tell which item moved, which was added, and which was removed, rather than guessing based on position.
- Always bind :key to something unique per item, such as a database id.
- Never use the array index as the key if items can be reordered, inserted, or removed.
- Keys should be primitive values (strings or numbers), not objects.
- A missing :key still renders, but you may see stale input values or transition glitches when the list changes.
- Keys only need to be unique among siblings in the same v-for, not globally.
v-for with index and :key
<div id="app">
<ol>
<li v-for="(task, index) in tasks" :key="task.id">
{{ index + 1 }}. {{ task.label }}
</li>
</ol>
</div>
<script>
const app = Vue.createApp({
data() {
return {
tasks: [
{ id: 101, label: 'Write the proposal' },
{ id: 102, label: 'Review the budget' },
{ id: 103, label: 'Send the invite' }
]
}
}
})
app.mount('#app')
</script>Looping Over Objects and Number Ranges
v-for isn't limited to arrays. Point it at a plain object and Vue will iterate its own enumerable properties, optionally exposing the value, key, and index. Point it at a plain integer n and Vue will loop from 1 through n, which is handy for star ratings, pagination dots, or generating placeholder rows.
v-for over object properties
<div id="app">
<ul>
<li v-for="(value, key) in product" :key="key">
<strong>{{ key }}:</strong> {{ value }}
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return {
product: {
name: 'Mechanical Keyboard',
price: 89,
inStock: true
}
}
}
})
app.mount('#app')
</script>Exercise: Vue v-for
Why does Vue recommend providing a unique :key when using v-for?