Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Directives  ›  Lesson

Rendering Lists with v-for

Rendering Lists 14 minv-for repeats an element for each item in a source, and a unique, stable key lets Vue track each item correctly.

Rendering Lists with v-for

Shelf's whole point is a list of books. You will not write one BookCard tag per book; the list grows and shrinks as people add and remove titles. v-for repeats an element once per item, and its key decides whether that list stays correct when it changes order.

The rule

v-for repeats; :key gives each copy a stable identity.

<ul>
  <li v-for="(book, index) in books" :key="book.id">
    {{ index + 1 }}. {{ book.title }}
  </li>
</ul>

Reading the parts:

  • book in books walks the array; book is available inside the element. The optional second name, index, is the position, starting at 0.
  • Objects can be looped too: v-for="(value, key) in book" gives each property value and its name.
  • Numbers give a range: v-for="n in 5" produces 1, 2, 3, 4, 5. It starts at 1, not 0.
  • <template v-for> repeats a group of elements without a wrapper.
  • :key must be a unique, stable value per item, usually an id from your data.

Why the key matters. When the array changes, Vue compares old and new elements by key. Same key → same element, moved if needed. If you use the index as the key, sorting keeps keys 0, 1, 2 in place, so Vue reuses each element where it stands and just patches its text. Anything held inside, such as a half-typed note in an input or a component's own state, stays at the old position and ends up next to the wrong book.

v-if and v-for on one element. In Vue 3, v-if is evaluated first, so <li v-for="book in books" v-if="!book.read"> fails: book does not exist yet when v-if runs. Filter with a computed (unread) and loop over that, or put v-for on a <template> wrapper and v-if on the element inside.

The shortcut

Before writing a loop, answer two questions: "What am I looping over?" and "What makes each item unique?" The second answer is your key.

Showing only unread booksStep 1 of 4
  1. What am I looping over?

    Only unread books, so make a computed: const unread = computed(() => books.value.filter(b => !b.read)).

Drills

Answer fast — trust the rule.

quick drill

What does <span v-for="n in 3">{{ n }}</span> render?

quick drill

Which is the best key for a list of books from a database?

quick drill

Cards are keyed by index. After sorting, a typed note appears on the wrong book. Why?

quick drill

Why does <li v-for="b in books" v-if="!b.read"> fail in Vue 3?

Remember

  • v-for="(item, index) in items" repeats an element; ranges start at 1.
  • Shortcut: "what am I looping over, and what makes each item unique?" The answer to the second is the key.
  • Trap: index keys on lists that reorder, and v-if with v-for on the same element.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhy a real key?

A teammate renders books with v-for="(book, i) in books" :key="i". Each BookCard has a text box for notes. After sorting by title, notes appear on the wrong books. Explain why and the fix.