Almost every screen shows or hides things and repeats things; getting keys right prevents subtle UI bugs.
`v-if`, v-else-if and v-else add or remove elements entirely. To toggle a group without a wrapper element, put v-if on a <template> tag, which renders nothing itself.
`v-show` keeps the element and toggles CSS display. Prefer it for things toggled very often (cheap to switch); prefer v-if when the condition rarely changes or the content is expensive (it is not rendered at all while false).
`v-for` repeats an element for each item:
- Arrays:
v-for="(item, index) in items". - Objects:
v-for="(value, key) in obj". - Ranges:
v-for="n in 5"gives 1 to 5.
Always give list items a `:key` with a stable, unique id (:key="todo.id"). Vue uses keys to match old and new elements when the list changes. Without them, or with the array index as key, Vue patches elements in place, so state inside items (input text, component state, focus) can end up attached to the wrong row after inserting, removing or sorting.
Don't put v-if and v-for on the same element. In Vue 3 v-if is evaluated first and cannot see the loop variable. Filter in a computed instead, or wrap with <template v-for> and put the v-if inside.
Example
<script setup>
import { ref, computed } from 'vue'
const todos = ref([
{ id: 1, text: 'Learn v-for', done: true },
{ id: 2, text: 'Use keys', done: false },
])
const hideDone = ref(false)
const visible = computed(() =>
hideDone.value ? todos.value.filter(t => !t.done) : todos.value)
</script>
<template>
<label><input type="checkbox" v-model="hideDone"> Hide done</label>
<ul v-if="visible.length">
<li v-for="(todo, i) in visible" :key="todo.id">
{{ i + 1 }}. {{ todo.text }}
</li>
</ul>
<p v-else>Nothing to do</p>
<p v-show="hideDone">Filtered view</p> <!-- stays in the DOM -->
</template>Remember
v-ifadds/removes elements;v-showtoggles CSS displayv-forneeds a stable unique:key, not the index, for dynamic lists- Filter with a computed instead of combining v-if and v-for
Watch out for
- Using the index as key in a list that can be reordered or have items removed.