Introduction

Using the Vue.js directive “v-for” we dynamically generate the so-called HTML. listing (mapping) data.
<div v-for="item in items">
Although it may seem logical at first glance to place the directive on the parent element (“ul” or “ol”), this is not the case here, with Vue.js the “v-for” directive is embedded on the HTML element that should be “listed”, i.e. The HTML element on which the “v-for” directive is “attached” will be used as a template for rendering the corresponding content.
The “v-for” directive uses a so-called “in-place patch” strategy that allows efficient use of resources. However, this approach can in some cases create a problem in displaying the listed elements, after sorting them or changing their order (for example, if we use a method that mixes the order). There is a solution to this problem by adding a unique “key” attribute to each element, which is “bind” to that element. Essentially adding this extra attribute is a cue for Vue.js to track the identity of each element and thus redefine the element’s position correctly. For the key, you should choose some unique data
v-bind:key="nekiJedinstveniParametar"
It is recommended to provide this attribute whenever possible. Read more about this issue on the official page or on the “codingexplained.com” page in the article “Understanding-v-for-update-strategy”
Example
|
1 2 3 |
<div v-for="item in items" v-bind:key="item.id" > <!-- content --> </div> |
String Mapping
Plain String Mapping
The general syntax looks like this:
|
1 2 3 |
v-for="(element) in array" // ili jednostavno: v-for="element in array" |
If index is also required, then the syntax is:
|
1 |
v-for="(element, index) in array" |
Example
See the Pen Plain String Mapping by Web programming (@chos) on CodePen.
As seen in the previous example, within the “v-for” block we also have full access to all other data properties (“city”).
Number sequence mapping
An ordinary number can be mapped with a similar syntax
Example
|
1 2 3 4 5 |
<div id="app"> <ul> <li v-for="n in 10">{{n}}</li> // 1,2,3,4,5,6,7,8,9,10 </ul> </div> |
or
|
1 2 3 4 5 6 |
<div id="app"> <ul> <li v-for="n in 10">{{11-n}}</li> // 10,9,8,7,6,5,4,3,2,1 </ul> <p>Launch missile!</p> </div> |
Mapping a series of objects with the same properties
Everything mentioned for listing a “regular” array also applies to listing an array containing objects:
See the Pen Listing an array of objects by Web programming (@chos) on CodePen.
Mapping an array of unequal objects
The preceding case of the given object looks like a list of objects from MySql database, where all objects have the same number of defined properties, but what if we use a MongDb database where notmust be? In that case, in order to list all properties (an object can have more or less properties), we need to put v-for on the “ul” tag, see example:
See the Pen
Untitled by Web Programming (@chos)
on CodePen.
Mapping mutated or filtered string
The “v-for” directive supports changing the mapped string with the methods: push(), pop(), shift(), unshift(), splice(), sort() and reverse(). However Vue.js does not support directly adding members as follows:
|
1 |
data.voce[4] = {cena: 10, naziv: 'ananas'} |
Vue 3 note (2026): In Vue 3, array index assignment is reactive — Vue.set / $set are not needed. Use arr[index] = value or arr.splice(...). Vue.set below is Vue 2 only.
Vue 2 solution: Vue.set()
|
1 2 3 4 5 |
// Vue 3 data.voce[4] = { cena: 10, naziv: 'ananas' }; // Vue 2 Vue.set(data.voce, 4, {cena: 10, naziv: 'ananas'}); |
Also Vue.js does not support string length modification as follows:
|
1 |
data.voce.length = 2 |
Conditional mapping with v-if
NOTE:
Do not use
v-for and
v-if on the same element. In Vue 3,
v-if has higher priority than
v-for (the opposite of Vue 2). Prefer wrapping with
<template> or filtering via a computed list.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<ul id="app"> <li v-for="proizvod in voce" v-if="proizvod.cena>10"> {{ proizvod.ime }} - {{ proizvod.cena }}din </li> </ul> <script> new Vue({ el:"#app", data: { voce: [ {ime: 'jabuka', cena: '7'}, {ime: 'pomorandza', cena: '12'}, {ime: 'banana', cena: '20'} ] } }) </script> |
The preceding code will list all filtered array members whose cost is greater than 10:
- orange – 12 dinars
- banana – 20 dinars
Filtering with the “computed” property
Instead of binding to a value from the “data” object, we can use the “computed” property to filter the string.
Example
See the Pen Filtering with enumeration – computed properties properties by Web programming (@chos) on CodePen.
NOTE:
In the previous example, pay attention to the expression
let vockaVanClosure = this.vocka; which allows us to use the value “vocka” as part of the closure function. Using “this.vock” within the callback function (closure) would not return the expected value “data” of the “vock” property, but “undefined”. You can read more about how the “this” keyword behaves in Vue.js in the article “Accessing Vue.js instance properties”
In this example, the computed property returns an array, so it’s simple to use filtrirajPoCeni.length to list how many species satisfy the condition. Also in this example we can add an attribute on each element “v-bind:key=”product.name” and thus prevent possible problems with sorting.
|
1 |
<li v-for="proizvod in filtrirajPoCeni" :key="proizvod.ime"> |
Filtering with method
Using the method gives the same result as in the previous example for the “computed” property:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<ul> <li v-for="proizvod in filtrirajPoCeni(voce)"> {{ proizvod.ime }} - {{ proizvod.cena }}din </li> </ul> <script> new Vue({ el:"#app", data: { voce: [ {ime: 'jabuka', cena: '7'}, {ime: 'pomorandza', cena: '12'}, {ime: 'banana', cena: '20'} ] }, methods:{ filtrirajPoCeni: function(niz) { return niz.filter(function(elementNiza) { return elementNiza.cena > 10; }) } } }) </script> |
To prevent problems that arise during sorting, i.e. in order to track the identities of each element, it is necessary to add some unique key to it.We can do this by binding a unique “key” attribute to each element with “v-bind:key=”product.name”.
|
1 |
<li v-for="proizvod in filtrirajPoCeni(voce)" :key="proizvod.ime"> |
Example
See the Pen filtering methods by Web programming (@chos) on CodePen.
Mapping object properties
The general syntax looks like this:
|
1 |
v-for="(value, key) in objekat" |
or if index is required the syntax for everything along with index is:
|
1 |
v-for="(value, key, index) in objekat" |
When iterating through object properties, “index” ranges from 0 to “n-1”, where n is the sequence number of the object property. The order in which the properties are listed is not fixed, in practice the order is usually the same as the order of inserting the properties, but this is not guaranteed either.
Example
An example of iteration through an object where all three attributes are used: value, key, index
See the Pen Listing object properties by Web Programming (@chos) on CodePen.
Example
In this example, rednering with the so-called “double loop”
See the Pen Double Loop by Web programming (@chos) on CodePen.
Element group mapping
The “v-for” directive can be applied to only one HTML element, and if it is necessary to map several HTML elements, we need to “wrap” them with a wrapper element to which we will “hang” our directive. That element can be <div> tag but it is recommended to be a <template> tag because it leaves no traces in the DOM.
See the Pen GyaVLE by Web programming (@chos) on CodePen.
Component Mapping
To list the components, we use the “for…in” syntax. Due to the already known problem with sorting, it is necessary to uniquely mark each component with a unique attribute “key”
v-bind:key="nekiJedinstveniParametar".
However, components have independent domains, so data will not be automatically inserted into the component. Therefore, in order to pass the data to the component, we have to “bind” it for each component
v-bind:item="item" and
v-bind:index="index"
|
1 2 3 4 5 6 |
<my-component v-for="(item, index) in items" v-bind:key="item.id"> v-bind:item="item" v-bind:index="index" </my-component> |
