Vue v-for in Components – Render Lists with Dynamic Components (2025 Guide)
Introduction – What Is v-for in Vue Components?
In Vue.js, v-for is a directive that enables you to loop over arrays or objects and render lists of elements or components. It’s especially powerful when used with components to dynamically render multiple instances, such as product cards, user profiles, or menu items.
In this guide, you’ll learn:
- How to use
v-forto render component lists - Pass props to each component instance
- Use
:keyfor efficient updates - Best practices for loops inside templates
What Is v-for?
The v-for directive repeats a block of template for each item in a data source, typically an array.
Syntax:
<template v-for="item in items">
<!-- repeated block -->
</template>
Basic List Rendering with Native Elements
<ul>
<li v-for="fruit in fruits" :key="fruit">{{ fruit }}</li>
</ul>
data() {
return {
fruits: ['Apple', 'Banana', 'Orange']
};
}
Each fruit will render as an individual <li> element.
Rendering Components with v-for
Let’s say you want to render a custom component for each product in a list.
Step 1: Create a Component – ProductCard.vue
<template>
<div class="card">
<h2>{{ product.name }}</h2>
<p>${{ product.price }}</p>
</div>
</template>
<script>
export default {
props: ['product']
}
</script>
Step 2: Use v-for to Render Component Instances
<ProductCard
v-for="item in products"
:key="item.id"
:product="item"
/>
data() {
return {
products: [
{ id: 1, name: 'Laptop', price: 899 },
{ id: 2, name: 'Phone', price: 499 }
]
};
}
Vue renders one <ProductCard> for each object in products, passing item as a prop.
Why Use :key with v-for?
The :key attribute helps Vue track element identity across updates. This improves performance and ensures stable DOM elements.
Always provide a unique and stable key, such as item.id.
Looping with Index
You can access the index of the current loop:
<li v-for="(fruit, index) in fruits" :key="index">
{{ index + 1 }}. {{ fruit }}
</li>
Prefer using a unique key over an index for dynamic lists.
Passing Multiple Props in a Loop
<UserCard
v-for="user in users"
:key="user.id"
:name="user.name"
:email="user.email"
/>
props: ['name', 'email']
Each instance gets its own name and email from the parent loop.
Real-World Example – Todo List
TodoItem.vue
<template>
<li>
<input type="checkbox" :checked="todo.done" @change="$emit('toggle', todo.id)" />
{{ todo.text }}
</li>
</template>
<script>
export default {
props: ['todo']
}
</script>
Parent Component
<ul>
<TodoItem
v-for="item in todos"
:key="item.id"
:todo="item"
@toggle="toggleTodo"
/>
</ul>
data() {
return {
todos: [
{ id: 1, text: 'Learn Vue', done: false },
{ id: 2, text: 'Build a project', done: true }
]
};
},
methods: {
toggleTodo(id) {
const todo = this.todos.find(t => t.id === id);
todo.done = !todo.done;
}
}
This is a complete reactive loop with child-to-parent event handling.
Common Mistakes to Avoid
Missing :key in loops
Always include a unique :key in v-for lists
Using index as key for dynamic data
Use item.id or another unique identifier instead
Mutating props inside the child
Emit events and handle data in the parent
Summary – Recap & Next Steps
Using v-for in Vue components allows you to dynamically render lists of reusable UI elements. It’s perfect for modular, scalable app design—whether you’re building a product catalog, blog post list, or todo app.
Key Takeaways:
- Use
v-forto loop over arrays or objects in templates - Combine
v-forwith components to render reusable UI blocks - Always use a unique
:keyfor stable updates - Pass props and emit events to communicate between components
Real-World Relevance:
This pattern is used everywhere in real Vue apps—cards, menus, modals, tables, user lists, and more.
FAQ Section
Can I use v-for on components?
Yes. It’s commonly used to render dynamic component lists like:
<MyComponent v-for="item in list" :key="item.id" :data="item" />
Why is the :key important in v-for?
It helps Vue efficiently track DOM elements during updates. It prevents glitches in animations and state preservation.
Can I use v-for with v-if on the same element?
Not recommended. Wrap v-if inside the loop block instead:
<div v-for="item in list" :key="item.id" v-if="item.visible"></div>
Can I emit events from components in a v-for loop?
Absolutely. Just pass a unique identifier and handle the event in the parent:
<ChildComp @delete="handleDelete(item.id)" />
How do I access the loop index in v-for?
Use (item, index):
<li v-for="(item, index) in items" :key="index">{{ index }}</li>
Share Now :
