The v-for directive is used to render collections of data by looping through arrays or object properties. It can also iterate over a range of numbers and work in combination with the <template> tag to repeat blocks of HTML.
Rendering Arrays
To display a list of items from an array, bind v-for to the element you wish to repeat. The syntax item in items assigns each element of the array to the varible item.
<ul>
<li v-for="city in cities" :title="city.label">{{ city.name }}</li>
</ul>
const app = {
data() {
return {
cities: [
{ name: "Beijing", label: "Capital of China" },
{ name: "Seoul", label: "Capital of South Korea" },
{ name: "Tokyo", label: "Capital of Japan" }
]
}
}
}
This renders:
Beijing
Seoul
Tokyo
You can access the current index by adding a second argument inside parentheses. The index is zero-based.
<ul>
<li v-for="(__item, __index) in cities" :title="__item.label">
{{ __item.name }} (Index: {{ __index }})
</li>
</ul>
Beijing (Index: 0)
Seoul (Index: 1)
Tokyo (Index: 2)
Iterating Over Objects
When iterating over an object, v-for provides access to the value, the key, and the index. The order is (value, key, index).
<ul>
<li v-for="(val, propKey, idx) in userProfile">
{{ propKey }}: {{ val }} (Order: {{ idx }})
</li>
</ul>
data() {
return {
userProfile: {
username: 'dev_alex',
role: 'Admin',
level: 99
}
}
}
Output:
username: dev_alex (Order: 0)
role: Admin (Order: 1)
level: 99 (Order: 2)
Looping Through a Range
v-for can generate a sequence of integers. Note that the count starts at 1, not 0.
<div>
<span v-for="n in 5" :key="n">Item {{ n }} </span>
</div>
This produces five span elements labeled Item 1 through Item 5.
Using <template> for Multiple Nodes
If you need to repeat a block containing multiple root elements with out introducing an extra wrapper div, use the <template> tag.
<template v-for="photo in gallery" :key="photo.id">
<h3>{{ photo.title }}</h3>
<img :src="photo.url" alt="Gallery image" />
<hr />
</template>
Instead of manually defining the array, you can use a computed property to generate the list dynamically.
computed: {
gallery() {
const items = [];
const baseUrl = 'https://example.com/photos/';
for (let x = 1; x <= 4; x++) {
items.push({
id: x,
title: `Photo ${x}`,
url: `${baseUrl}img_${x}.jpg`
});
}
return items;
}
}
Reactivity Caveats
Vue cannot detect direct index assignment or modification of array length. If you have a list of primitive values:
data() {
return {
scores: [10, 20, 30]
}
}
Setting this.scores[0] = 50 will not update the view. You must use the reactive set method:
// Incorrect: this.scores[0] = 50
// Correct:
this.$set(this.scores, 0, 50);
// Or globally: Vue.set(this.scores, 0, 50)