v-for and List Rendering
v-for renders a list of elements from an array or object. It is how FamilyTree renders every list: all parents, all children, all former spouses, the people sidebar.
Rendering an array
Section titled “Rendering an array”<script setup lang="ts">const people = [ { id: '1', name: 'Alice' }, { id: '2', name: 'Bob' }, { id: '3', name: 'Carol' },]</script>
<template> <ul> <li v-for="person in people" :key="person.id"> {{ person.name }} </li> </ul></template>The syntax is v-for="item in array". Each iteration has access to item.
The :key attribute
Section titled “The :key attribute”:key is required with v-for. It must be a unique, stable identifier — typically the item’s id. Vue uses it to track which list items correspond to which DOM elements when the array changes.
Without :key, Vue may re-use the wrong DOM element when items are added, removed, or reordered — causing subtle bugs with input state, animations, or transitions.
<!-- ✅ Correct — stable unique key --><PersonCard v-for="p in people" :key="p.id" :person="p" />
<!-- ❌ Avoid — index as key causes issues when list changes --><PersonCard v-for="(p, index) in people" :key="index" :person="p" />Use the array index as the key only when the list is completely static and never reordered.
Accessing the index
Section titled “Accessing the index”The second parameter gives the current index:
<li v-for="(person, index) in people" :key="person.id"> {{ index + 1 }}. {{ person.name }}</li>Iterating over an object
Section titled “Iterating over an object”v-for also works on objects:
<li v-for="(value, key) in person" :key="key"> {{ key }}: {{ value }}</li>Rendering components with v-for
Section titled “Rendering components with v-for”Use v-for with components the same way as with elements:
<PersonCard v-for="person in parents" :key="person.id" :person="person" role="parent" :clickable="true" @select="focusOn"/>Each PersonCard instance gets its own set of props. When parents changes, Vue reconciles the list using the :key values.
v-for with v-if
Section titled “v-for with v-if”Avoid using v-if and v-for on the same element — Vue 3 evaluates v-if first, which means the loop variable isn’t available in the condition.
Instead, wrap with a <template> or filter the array in a computed:
<!-- ✅ Preferred — filter in computed --><PersonCard v-for="p in activeParents" :key="p.id" :person="p"/>
<!-- ❌ Avoid — v-if and v-for on same element --><PersonCard v-for="p in people" v-if="p.isParent" :key="p.id"/>Exercise
Section titled “Exercise”- Create a component with a
ref<{ id: string; name: string }[]>array. - Render each item using
v-forwith aPersonCardcomponent, passingnameas a prop. - Add a button that pushes a new person to the array. Verify the list updates.
- Add a button next to each person that removes them from the array using
.filter().
v-for="item in array"renders an element for each item.:keyis required — use a stable unique identifier, not the array index.- Access the index as the second parameter:
v-for="(item, index) in array". - Combine
v-forwith components exactly as with HTML elements. - Filter arrays in a
computedrather than usingv-ifon the same element asv-for.