Introduction
A common requirement for front-end applications is listing out items. It can take the form of a to-do list and card systems. Vue.js supports rendering lists of items onto the browser using the built-in v-for<
core directive.
In this post, we will explore how v-for
can be used in Vue applications.
Prerequisites
This post assumes you have some knowledge of loops, arrays, and objects in JavaScript. You can refer to this series if you’re getting started with JavaScript.
This exploration will build upon an HTML file that uses a CDN (content delivery network) hosted copy of the Vue.js framework:
vfor.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-for</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
<script>
new Vue({
el: "#app",
data() {
return {
message: "hello"
}
}
});
</script>
</body>
</html>
You can refer to this post if you’re getting started with Vue.js.
At this point, if you were to upload this code and view this file in a browser, you will see the message: "hello"
.
Using v-for
with Range
The built-in v-for
directive allows us to loop through items.
We can use a range in the v-for
directive to iterate a specified number of times.
Let’s replace the contents of our <div>
with an unordered list that repeats list items 15 times:
vfor.html
<div id="app">
<ul>
<li v-for="item in 15">{{ item }}</li>
</ul>
</div>
This will result in an unordered list with numbers 1
to 15
.
Using the <template>
Element
The v-for
directive only applies to the element that it’s attached to. If multiple items should repeat with the v-for
directive, we should wrap the elements in a <template>
element.
Let’s replace the contents of our <div>
with a <template>
:
vfor.html
<div id="app">
<template v-for="item in 15">
<span>{{ item }}</span>
<button>Count</button>
</template>
</div>
This will result in a collection of repeating <span>
s and <button>
s.
Using v-for
with Objects
We can loop over the values in an objectItems
object from the data model. This can be accomplished by adding the v-for
directive in the element that should be repeated.
Let’s modify the lines in data()
so it returns an objectItems
object:
vfor.html
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
}
}
}
});
</script>
Let’s replace the contents of our <div>
with an unordered list that repeats list items:
vfor.html
<div id="app">
<ul>
<li v-for="item in objectItems">{{ item }}</li>
</ul>
</div>
Here’s how things will look:
<div id="app">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
This will result in an unordered list with the property values from the object.
In addition to the property value, we get two additional parameters when looping over objects with Vue. Namely, the key
and the index
values.
The key
value gives us access to the current properties key.
The index
provides us the index of the current item in the loop. This is the position of the item in the looped list.
Let’s replace the contents of our <div>
with an unordered list that repeats list items with item
, key
, and index
:
vfor.html
<div id="app">
<ul>
<li v-for="(item, key, index) in objectItems">
{{ item }} - {{ key }} - {{ index }}
</li>
</ul>
</div>
Here’s how things will look:
<div id="app">
<ul>
<li>item1 - key1 - 1</li>
<li>item2 - key2 - 2</li>
<li>item3 - key3 - 3</li>
</ul>
</div>
This will result in an unordered list with the item
, key
, and index
.
Using v-for
with Arrays
We can loop over the items in a shoppingItems
array from the data model. This can be accomplished by adding the v-for
directive in the element that should be repeated.
Let’s modify the lines in data()
so it returns a shoppingItems
array with objects:
vfor.html
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
},
shoppingItems: [
{ name: 'apple', price: '7' },
{ name: 'orange', price: '12' }
]
}
}
});
</script>
We can loop over the objects in the shoppingItems
array and access the values using a given key.
Let’s replace the contents of our <div>
with an unordered list that repeats list items with item.name
and item.price
:
vfor.html
<div id="app">
<ul>
<li v-for="item in shoppingItems">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Here’s how things will look:
<div id="app">
<ul>
<li>apple - 7</li>
<li>orange - 12</li>
</ul>
</div>
This will result in an unordered list with the values from the array.
Using v-bind:key
to Track Elements
When the array order is changed, by default Vue would change the data in each existing element rather than moving the DOM elements to the updated position.
We can set Vue to track each element using a key. This would cause it to move elements rather than replacing values.
This value should be unique to each element that’s being iterated over.
Let’s assign a key using item.name
:
vfor.html
<div id="app">
<ul>
<li v-for="item in shoppingItems" v-bind:key="item.name">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Now, Vue has a way of tracking a node’s identity as changes are made.
Managing Changes
Out of the box, v-for
supports array mutation methods. These are push
, pop
, shift
, unshift
, splice
, sort
and reverse
. If any of these operations are performed on an array, the v-for
directive updates the view with the new data.
Also, when we replace an array with a new array, Vue finds the most optimized way to update the items.
Problems with Change Management
The two things that Vue cannot track when changed in an array are:
Setting items directly.
Example:
data.shoppingItems[3] = { price: 10, name: 'pineapple' };
This can be resolved by using the Vue.set
method. This method accepts the array
, an index
, and the new value
.
Vue.set(data.shoppingItems, 3, { price: 10, name: 'pineapple' });
Also, we can use splice
to set the value at a given index.
Modifying array length.
Example:
data.shoppingItems.length = 2;
We can use splice
to modify the array length instead of setting it directly to avoid issues.
Filtering Lists
We can filter out lists that are being displayed without changing the original list. This can be done using computed
values or by having a method and passing values through when setting the v-for
values.
Using computed
Values to Filter Items
Instead of setting the value directly on the list, we instead point to a computed
value. We can write the logic for filtering out data in that computed function.
First, let’s define itemsLessThanTen
:
vfor.html
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
},
shoppingItems: [
{ name: 'apple', price: '7' },
{ name: 'orange', price: '12' }
]
}
},
computed: {
itemsLessThanTen: function() {
return this.shoppingItems.filter(function(item) {
return item.price < 10;
})
}
}
});
</script>
Then, let’s modify the v-for
to use itemsLessThanTen
:
vfor.html
<div id="app">
<ul>
<li v-for="item in itemsLessThanTen" v-bind:key="item.name">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Here’s how things will look:
<div id="app">
<ul>
<li>apple - 7</li>
</ul>
</div>
The itemLessThanTen
function uses the JavaScript filter
function to return any item with a price is less than 10.
Using a Method to Filter Items
In this approach, we pass in the same shoppingItems
list directly to a method that we define. By doing so, all the items in the array would be filtered according to the method definition.
First, let’s define filterItems
:
vfor.html
<script>
new Vue({
el: "#app",
data() {
return {
objectItems: {
key1: 'item1',
key2: 'item2',
key3: 'item3'
},
shoppingItems: [
{ name: 'apple', price: '7' },
{ name: 'orange', price: '12' }
]
}
},
computed: {
itemsLessThanTen: function() {
return this.shoppingItems.filter(function(item) {
return item.price < 10;
})
}
},
methods: {
filterItems: function(items) {
return items.filter(function(item) {
return item.price < 10;
})
}
}
});
</script>
Then, let’s modify the v-for
to use filterItems
:
vfor.html
<div id="app">
<ul>
<li v-for="item in filterItems(shoppingItems)" v-bind:key="item.name">
{{ item.name }} - {{ item.price }}
</li>
</ul>
</div>
Here’s how things will look:
<div id="app">
<ul>
<li>apple - 7</li>
</ul>
</div>
The filterItems
method performs the same function as in the computed
value example, and the final result would be the same.
Conclusion
In this article, you learned about using v-for
in Vue applications. You were introduced to ranges, keys, computed
, and methods
.
If you’d like to learn more about Vue.js, check out our Vue.js topic page for exercises and programming projects.