🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

List Rendering (v-for) in Vue.js

Learn about List Rendering (v-for) in this comprehensive Vue.js tutorial. Master the v-for directive and understand why the :key attribute is absolutely critical for performance.

Total XP: 0|💻 vuejs XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

Select an unlocked node to view details root

🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Render arrays and objects dynamically in the DOM.

1Iterating over Arrays

We can use the v-for directive to render a list of items based on an array. The directive requires a special syntax in the form of item in items, where items is the source data array.

2The Importance of Keys

When Vue is updating a list of elements rendered with v-for, by default it uses an 'in-place patch' strategy. If the order of the data items has changed, Vue will patch each element in-place. To give Vue a hint so it can track each node's identity, you must provide a unique :key attribute.

3Iterating over Objects

You can also use v-for to iterate through the properties of an object. The syntax is (value, key, index) in myObject.

4Step-by-Step Breakdown

Web apps are mostly just lists of data: Tweets, Products, Emails. To render lists in Vue, we use the v-for directive.

The syntax for v-for is item in items, where items is your source data array, and item is an alias for the array element being iterated on.

What directive do you use to render a list of items from an array in Vue?

  • v-map
  • v-for
  • v-repeat

You can also extract the index of the current item by using parentheses: (item, index) in items.

CRITICAL RULE: When using v-for, you MUST provide a unique key attribute for each item. This helps Vue track changes and optimize rendering.

What attribute is MANDATORY to include when rendering lists with v-for so Vue can track node identity?

  • id
  • key
  • index

You should NEVER use the array index as the key if the list can be reordered or have items deleted. Always use a unique ID from your database.

v-for can also iterate over the properties of an Object, not just Arrays!

When iterating over an Object using v-for="(value, key) in object", which argument represents the property name (like "author")?

  • value
  • key

With v-if and v-for, you now have the power to render dynamic, data-driven interfaces. Let's keep building!

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Keying Ensures Accessible State Survives Reordering

When a v-for list uses a stable :key (an item's database id), Vue preserves and moves the actual DOM node during reordering instead of destroying and recreating it — so focus position, an expanded/collapsed ARIA state, or an in-progress form input inside a list item survives a re-sort or filter, instead of resetting and disorienting keyboard and screen-reader users.

<li v-for="task in tasks" :key="task.id"> <input v-model="task.note" /> </li>

SEO Implications

  • 1

    v-for Renders Every Item Into Real DOM Nodes, Fully Crawlable

    There's no virtualization or lazy rendering built into v-for itself — every element in the source array becomes an actual DOM node (and, during SSR, actual HTML), so a v-for list of 200 blog post links is exactly as indexable as 200 manually written <a> tags. Virtual-scrolling libraries that only render visible rows are a separate opt-in with their own SSR considerations.

Best Practices

Never Use the Array Index as :key If the List Can Reorder

Using :key="index" defeats the purpose of keying whenever items can be added, removed, filtered, or sorted, because the index-to-item mapping shifts even though the key values look unchanged to Vue — leading to state like a checked checkbox sticking to the wrong row. Use a stable identifier from the data itself.

Frequent Bugs

THE BUG

Combining v-if and v-for on the exact same element.

THE FIX

In Vue 3, v-if has higher precedence than v-for on the same node, so the v-if condition cannot access the v-for scope variable and Vue raises a compile-time error. Move the filtering into a computed property, or wrap the loop in a <template v-for="..."> with the v-if on the element inside it.

Real-World Examples

Rendering a Paginated Comment Thread

A comments component renders v-for="comment in visibleComments" :key="comment.id", where visibleComments is a computed property slicing the full comments array by the current page number, keeping the v-for simple while all pagination math lives in one computed.

const visibleComments = computed(() =>
  comments.value.slice(page.value * 20, (page.value + 1) * 20)
);

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Mutating a Prop Directly

// Wrong const props = defineProps(['count']); function increment() { props.count++; } // Correct const emit = defineEmits(['update:count']); function increment() { emit('update:count', props.count + 1); }

The Solution //

A child component should never assign to a prop it received (e.g. props.title = 'New'). Vue logs "Unexpected mutation of prop" because props are a one-way binding. Copy the prop into local state with ref()/computed() first, or emit an event asking the parent to change its own data.

The Error //

Losing Reactivity by Destructuring reactive()

// Wrong const { name } = reactive({ name: 'Alice' }); // name is now a static string // Correct const state = reactive({ name: 'Alice' }); const { name } = toRefs(state); // name is a live ref

The Solution //

Destructuring a reactive() object copies its properties out as disconnected plain values, so future mutations of the original object won't update the destructured variables. Keep referencing the object's properties directly, or convert it with toRefs() before destructuring.

Continue Learning