Skip to content

v-for

The v-for directive is used to render an element or template block multiple times based on the data source, such as an array, object, or numeric range.

With an Array

You can use v-for to render a list of items from an array. The directive uses a special syntax in the form of item in items, where items is the source array and item is an alias for the current element being iterated:

vue
<div v-for="item in items">
  {{ item.text }}
</div>

You can also specify a second alias for the index:

vue
<div v-for="(item, index) in items"></div>

With an Object

v-for can also be used to iterate over the properties of an object. By default, the iteration order is based on the result of calling Object.values() on the object:

vue
<ul>
  <li v-for="value in myObject">
    {{ value }}
  </li>
</ul>

You can also provide a second alias for the property's name (a.k.a. key):

vue
<li v-for="(value, key) in myObject"> ... </li>

You may also include a third alias for the index:

vue
<li v-for="(value, key, index) in myObject"> ... </li>

With a Range

v-for can also accept an integer. In this case it will repeat the element or template a specified number of times, generating a range from 1 to n:

vue
<span v-for="n in 10">{{ n }}</span>

NOTE

In range-based iteration, the value of n starts at 1, not 0.

On the <template> tag

Similar to v-if, you can also use a <template> tag with v-for to render a block of multiple elements. For example:

vue
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

Maintaining State with key

When Vue updates a list rendered with v-for, it tries to reuse existing DOM elements for efficiency. By default, this reuse is based on position in the list, not on the identity of each item.

To help Vue track each item correctly (especially when items are added, removed, or reordered), you should provide a unique key attribute for each item:

vue
<div v-for="item in items" :key="item.id">
  {{ item.text }}
</div>

The key tells Vue how each element corresponds to the underlying data. This allows Vue to preserve internal state (such as input values or focus) and apply updates more predictably.

TIP

The value of key should be a unique and stable identifier. Avoid using the array index as a key unless the list is static and will never change.

With v-if

It is possible to use v-if and v-for on the same element, however v-if has a higher priority and is evaluated first. That means the v-if condition will not have access to variables from the scope of the v-for:

vue
<!--
This will throw an error because property "todo"
is not defined on instance.
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo.name }}
</li>

This can be fixed by moving v-for to a wrapping <template> tag (which is also more explicit):

vue
<template v-for="todo in todos">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>

WARNING

It's not recommended to use v-if and v-for on the same element due to implicit precedence.

With a Component

In addition to plain HTML elements, v-for can also be used to render Vue components multiple times.

When rendering components with v-for, it is especially important to provide a key. The key allows Vue to correctly track each component instance across updates, ensuring that state and DOM behavior stay in sync when the list changes.

Unlike plain HTML elements, components do not automatically know which item in the list they are rendering. For that reason, you typically pass the current item (and optionally the index) to each component so it has access to the data it should display.

Components receive their data through attributes (called props), which you’ll learn about later.

Here is an example:

vue
<MyComponent
  v-for="(item, index) in items"
  :key="item.id"
  :item="item"
  :index="index"
/>