Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Lists and Keys

v-for — Rendering Lists

The v-for directive renders a list of items based on an array or object. Always provide a :key attribute with a unique, stable identifier — this helps Vue efficiently update the DOM when the list changes.

v-for — Arrays, Objects, Ranges, Filtering, Sorting
<template>
  <div>
    <!-- Array with index -->
    <ul>
      <li v-for="(fruit, index) in fruits" :key="fruit">
        {{ index + 1 }}. {{ fruit }}
      </li>
    </ul>

    <!-- Array of objects — use stable ID as key -->
    <div v-for="user in users" :key="user.id" class="user-card">
      <h3>{{ user.name }}</h3>
      <p>{{ user.email }}</p>
    </div>

    <!-- Object properties -->
    <dl>
      <template v-for="(value, key, index) in person" :key="key">
        <dt>{{ index + 1 }}. {{ key }}</dt>
        <dd>{{ value }}</dd>
      </template>
    </dl>

    <!-- Range (1 to n) -->
    <span v-for="n in 5" :key="n">{{ n }} </span>

    <!-- Nested v-for -->
    <div v-for="category in categories" :key="category.id">
      <h3>{{ category.name }}</h3>
      <ul>
        <li v-for="item in category.items" :key="item.id">
          {{ item.name }}
        </li>
      </ul>
    </div>

    <!-- Filtered list with computed -->
    <input v-model="search" placeholder="Search..." />
    <ul>
      <li v-for="user in filteredUsers" :key="user.id">
        {{ user.name }}
      </li>
    </ul>

    <!-- v-for + v-if — use <template> to avoid conflict -->
    <template v-for="user in users" :key="user.id">
      <div v-if="user.isActive">{{ user.name }}</div>
    </template>
  </div>
</template>

<script setup>
import { ref, reactive, computed } from 'vue'

const fruits = ref(['Apple', 'Banana', 'Cherry', 'Date'])
const users = reactive([
  { id: 1, name: 'Alice', email: 'alice@example.com', isActive: true },
  { id: 2, name: 'Bob',   email: 'bob@example.com',   isActive: false },
  { id: 3, name: 'Carol', email: 'carol@example.com', isActive: true },
])
const person = reactive({ name: 'Alice', age: 25, city: 'NYC' })
const categories = reactive([
  { id: 1, name: 'Fruits', items: [{ id: 11, name: 'Apple' }, { id: 12, name: 'Banana' }] },
  { id: 2, name: 'Veggies', items: [{ id: 21, name: 'Carrot' }] },
])
const search = ref('')

const filteredUsers = computed(() =>
  users.filter(u => u.name.toLowerCase().includes(search.value.toLowerCase()))
)
</script>
<template>
  <div>
    <div class="controls">
      <input v-model="newTask" @keyup.enter="addTask" placeholder="New task..." />
      <select v-model="sortBy">
        <option value="name">Sort by Name</option>
        <option value="priority">Sort by Priority</option>
      </select>
    </div>

    <TransitionGroup name="list" tag="ul">
      <li v-for="task in sortedTasks" :key="task.id" class="task-item">
        <input type="checkbox" v-model="task.done" />
        <span :class="{ done: task.done }">{{ task.name }}</span>
        <select v-model="task.priority">
          <option value="high">High</option>
          <option value="medium">Medium</option>
          <option value="low">Low</option>
        </select>
        <button @click="removeTask(task.id)">✕</button>
      </li>
    </TransitionGroup>

    <p>{{ tasks.filter(t => t.done).length }} / {{ tasks.length }} done</p>
  </div>
</template>

<script setup>
import { ref, reactive, computed } from 'vue'

const newTask = ref('')
const sortBy = ref('name')
const tasks = reactive([
  { id: 1, name: 'Learn Vue', priority: 'high',   done: false },
  { id: 2, name: 'Build app', priority: 'medium', done: false },
  { id: 3, name: 'Deploy',    priority: 'low',    done: false },
])

const sortedTasks = computed(() => {
  return [...tasks].sort((a, b) => {
    if (sortBy.value === 'name') return a.name.localeCompare(b.name)
    const order = { high: 0, medium: 1, low: 2 }
    return order[a.priority] - order[b.priority]
  })
})

function addTask() {
  if (!newTask.value.trim()) return
  tasks.push({ id: Date.now(), name: newTask.value, priority: 'medium', done: false })
  newTask.value = ''
}

function removeTask(id) {
  const idx = tasks.findIndex(t => t.id === id)
  if (idx !== -1) tasks.splice(idx, 1)
}
</script>

<style>
.list-enter-active, .list-leave-active { transition: all 0.3s ease; }
.list-enter-from, .list-leave-to { opacity: 0; transform: translateX(-20px); }
.list-move { transition: transform 0.3s ease; }
.done { text-decoration: line-through; opacity: 0.5; }
</style>

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.