Vue.js List Rendering

List rendering lets you display every item in an array or object without writing a separate HTML element for each one. Vue's v-for directive loops through a collection and generates the HTML automatically.

The v-for Directive

v-for repeats an HTML element for each item in an array. You define a temporary variable name for the current item and provide the array to loop through.

<div id="app">
  <ul>
    <li v-for="fruit in fruits" :key="fruit">
      {{ fruit }}
    </li>
  </ul>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        fruits: ["Apple", "Banana", "Mango", "Orange"]
      };
    }
  }).mount("#app");
</script>

Output:

• Apple
• Banana
• Mango
• Orange

Diagram: How v-for Expands

Template (written once):
  <li v-for="fruit in fruits">{{ fruit }}</li>

fruits array: ["Apple", "Banana", "Mango", "Orange"]

Vue generates:
  <li>Apple</li>
  <li>Banana</li>
  <li>Mango</li>
  <li>Orange</li>

The :key Attribute — Why It Matters

Vue needs a unique :key on every element in a v-for loop. This key helps Vue track which item is which when the list changes. Without it, Vue might update the wrong element when items are added, removed, or reordered.

Think of the key like a name tag at a conference. Without name tags, if someone leaves and a new person arrives in the same seat, you might confuse the two people. Name tags prevent that confusion.

<!-- Always provide :key -->
<li v-for="fruit in fruits" :key="fruit">{{ fruit }}</li>

<!-- For arrays of objects, use the unique ID -->
<li v-for="item in items" :key="item.id">{{ item.name }}</li>

The key should be unique for each item. For simple arrays of strings, the string itself works. For arrays of objects, use a unique ID field.

Accessing the Index

v-for gives you a second optional variable — the current item's position (index) in the array, starting at 0.

<ol>
  <li v-for="(fruit, index) in fruits" :key="fruit">
    {{ index + 1 }}. {{ fruit }}
  </li>
</ol>

Output:

1. Apple
2. Banana
3. Mango
4. Orange

Looping Through an Array of Objects

Most real data comes as an array of objects. You access each object's properties using dot notation inside the loop.

<div id="app">
  <div v-for="student in students" :key="student.id">
    <h4>{{ student.name }}</h4>
    <p>Grade: {{ student.grade }} | Score: {{ student.score }}</p>
  </div>
</div>

<script>
  Vue.createApp({
    data() {
      return {
        students: [
          { id: 1, name: "Alice",   grade: "A", score: 95 },
          { id: 2, name: "Bob",     grade: "B", score: 82 },
          { id: 3, name: "Charlie", grade: "C", score: 71 }
        ]
      };
    }
  }).mount("#app");
</script>

Diagram: Object Array Rendering

students[0] → { id: 1, name: "Alice",   grade: "A", score: 95 }
students[1] → { id: 2, name: "Bob",     grade: "B", score: 82 }
students[2] → { id: 3, name: "Charlie", grade: "C", score: 71 }

Renders:
┌────────────────────────────┐
│ Alice                      │
│ Grade: A | Score: 95       │
├────────────────────────────┤
│ Bob                        │
│ Grade: B | Score: 82       │
├────────────────────────────┤
│ Charlie                    │
│ Grade: C | Score: 71       │
└────────────────────────────┘

Looping Through an Object's Properties

v-for also works on plain JavaScript objects. It loops through each key-value pair.

data() {
  return {
    profile: {
      name: "Jordan Lee",
      city: "Austin",
      role: "Developer"
    }
  };
}

<ul>
  <li v-for="(value, key) in profile" :key="key">
    {{ key }}: {{ value }}
  </li>
</ul>

Output:

• name: Jordan Lee
• city: Austin
• role: Developer

Looping a Fixed Number of Times

You can pass a number to v-for to repeat an element a set number of times.

<span v-for="n in 5" :key="n">★</span>

Output:

★ ★ ★ ★ ★

This is useful for star ratings, pagination dots, or any fixed repeating element.

Combining v-for with v-if

Do not put v-if and v-for on the same element — Vue processes v-if first, so it may not have access to the loop variable. Instead, wrap the element in a <template v-for> and place v-if on the inner element.

<!-- WRONG: v-if and v-for on the same element -->
<li v-for="item in items" v-if="item.inStock" :key="item.id">
  {{ item.name }}
</li>

<!-- CORRECT: use template wrapper -->
<template v-for="item in items" :key="item.id">
  <li v-if="item.inStock">{{ item.name }}</li>
</template>

Diagram: Filtered List with Template

items = [
  { id: 1, name: "Chair",  inStock: true  },
  { id: 2, name: "Table",  inStock: false },
  { id: 3, name: "Lamp",   inStock: true  }
]

Loop processes all 3 items.
v-if filters:
  Chair  → inStock: true  → shown
  Table  → inStock: false → hidden
  Lamp   → inStock: true  → shown

Result:
  • Chair
  • Lamp

Reactive List Updates

Vue detects changes to arrays and updates the displayed list automatically. The following array methods trigger an update:

  • push() — adds an item to the end
  • pop() — removes the last item
  • shift() — removes the first item
  • unshift() — adds an item to the beginning
  • splice() — adds or removes items at a position
  • sort() — reorders items
  • reverse() — reverses the order
<div id="app">
  <ul>
    <li v-for="task in tasks" :key="task">{{ task }}</li>
  </ul>
  <button @click="addTask">Add Task</button>
</div>

<script>
  Vue.createApp({
    data() {
      return { tasks: ["Design mockup", "Write tests"] };
    },
    methods: {
      addTask() {
        this.tasks.push("Deploy update");
      }
    }
  }).mount("#app");
</script>

Diagram: Push Triggers Reactive Update

Before click:
tasks = ["Design mockup", "Write tests"]
Page shows: • Design mockup  • Write tests

User clicks "Add Task"
  → tasks.push("Deploy update")

Vue detects the change:
tasks = ["Design mockup", "Write tests", "Deploy update"]
Page shows: • Design mockup  • Write tests  • Deploy update
            (no page reload — Vue updates only the list)

Summary

The v-for directive repeats HTML elements for each item in an array or object. Always include a unique :key to help Vue track items efficiently. Use the (item, index) syntax to access the loop position. For arrays of objects, access properties with dot notation. Use a <template> wrapper when combining v-for and v-if. Mutating methods like push() trigger Vue's reactivity automatically, keeping the list in sync with your data.

Leave a Comment

Your email address will not be published. Required fields are marked *