Directives: v-if, v-for, v-bind, v-model

beginner
14 min

Directives: v-if, v-for, v-bind, v-model

Directives are special attributes prefixed with v- that give templates superpowers: conditionally render blocks, loop over lists, bind data to attributes, and wire form inputs to state. Mastering the four core directives in this lesson covers 90% of everyday template work in Vue 3.

Conditional Rendering: v-if, v-else-if, v-else

v-if renders an element only when its expression is truthy:

vue
<script setup> import { ref } from 'vue' const status = ref('loading') </script> <template> <p v-if="status === 'loading'">Loading…</p> <p v-else-if="status === 'error'">Something went wrong.</p> <p v-else>Data loaded!</p> </template>

v-else and v-else-if must immediately follow a v-if sibling. To toggle several elements together without adding a wrapper div, put v-if on a <template> tag -- it renders its children with no extra DOM node.

v-if vs v-show

v-show keeps the element in the DOM and toggles display: none. Use v-show for things that toggle frequently (cheap to switch, costly upfront) and v-if for branches that rarely change or are expensive to create.

List Rendering: v-for

v-for repeats an element for each item in an array, object, or range:

vue
<script setup> import { ref } from 'vue' const todos = ref([ { id: 1, text: 'Learn directives', done: true }, { id: 2, text: 'Build an app', done: false } ]) </script> <template> <ul> <li v-for="(todo, index) in todos" :key="todo.id"> {{ index + 1 }}. {{ todo.text }} </li> </ul> </template>

Always provide :key with a stable, unique value (an id, not the index). Keys let Vue track each node's identity so reordering, inserting, and deleting items updates the DOM correctly and efficiently. Avoid combining v-if and v-for on the same element; wrap one in a <template> instead, because v-if has higher priority in Vue 3 and cannot see the loop variable.

You can also iterate objects (v-for="(value, key) in user") and ranges (v-for="n in 5").

Attribute Binding: v-bind

You met v-bind in the previous lesson; here are the patterns you will use daily:

vue
<a :href="profileUrl" :title="'Visit ' + userName">Profile</a> <input :placeholder="hint" :maxlength="limit"> <div :class="[baseClass, isActive ? 'on' : 'off']"></div>

Binding an object of attributes at once is possible with v-bind="attrsObject", which spreads every key as an attribute.

Two-Way Binding: v-model

v-model creates a two-way link between a form input and your state -- typing updates the data, and updating the data changes the input:

vue
<script setup> import { ref } from 'vue' const message = ref('') const agreed = ref(false) const picked = ref('vue') </script> <template> <input v-model="message" placeholder="Type here"> <p>You typed: {{ message }}</p> <input type="checkbox" v-model="agreed"> I agree <select v-model="picked"> <option value="vue">Vue</option> <option value="react">React</option> </select> </template>

v-model adapts automatically: text inputs bind value, checkboxes bind checked, selects bind the selected option. Three useful modifiers:

  • v-model.trim strips whitespace from the ends.
  • v-model.number casts the input to a number.
  • v-model.lazy syncs on change instead of every keystroke.

Putting It Together

vue
<template> <input v-model.trim="newTodo" @keyup.enter="addTodo" placeholder="Add a task"> <p v-if="todos.length === 0">Nothing to do 🎉</p> <ul v-else> <li v-for="todo in todos" :key="todo.id" :class="{ done: todo.done }"> <input type="checkbox" v-model="todo.done"> {{ todo.text }} </li> </ul> </template>

This tiny todo template combines all four directives -- exactly how real Vue apps are built.

Key Takeaways

  • v-if/v-else-if/v-else add or remove elements; v-show merely hides them.
  • v-for needs a stable :key; never key by array index if the list reorders.
  • Do not put v-if and v-for on the same element in Vue 3.
  • v-model gives two-way binding on inputs, with .trim, .number, and .lazy modifiers.

Next up: Handling Events -- listening to clicks, key presses, and more with v-on.

Directives: v-if, v-for, v-bind, v-model - Vue.js | CodeYourCraft | CodeYourCraft