Using the v-for Directive in Vue.js for Dynamic Rendering

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)

Tags: Vue.js v-for Frontend Development javascript Directives

Posted on Mon, 31 Aug 2026 16:54:41 +0000 by lives4him06