Tutorials Logic, IN info@tutorialslogic.com

Vue Directives v if, v for, v model, v bind

DOM Behavior Directives

A custom directive packages low-level behavior applied directly to an element. Use one when the concern is fundamentally about DOM lifecycle, such as focus management, intersection observation, or integrating a library that needs an element. Reusable stateful logic without direct element manipulation belongs in a composable.

What are Directives?

Directives are special attributes with the v- prefix that apply reactive behavior to the DOM. They are Vue's way of extending HTML with dynamic functionality.

Directive Purpose Shorthand
v-if / v-else-if / v-else Conditional rendering (removes from DOM) -
v-show Toggle visibility (keeps in DOM) -
v-for Render list -
v-bind Bind attribute to data :
v-on Listen to events @
v-model Two-way data binding -
v-text Set text content -
v-html Set raw HTML -
v-once Render once, skip updates -
v-pre Skip compilation -

All Vue Directives - Complete Examples

All Vue Directives - Complete Examples
<template>
  <div>
    <!-- v-if / v-else-if / v-else - removes from DOM -->
    <div v-if="role === 'admin'">Admin Panel</div>
    <div v-else-if="role === 'user'">User Dashboard</div>
    <div v-else>Guest View</div>

    <!-- v-show - toggles display:none, stays in DOM -->
    <div v-show="isVisible">I'm visible: {{ isVisible }}</div>
    <!-- Use v-show for frequent toggles, v-if for rare ones -->

    <!-- v-bind shorthand : -->
    <img :src="imgSrc" :alt="imgAlt" :class="{ rounded: isRound }" />
    <a :href="url" :target="newTab ? '_blank' : '_self'">Link</a>

    <!-- v-on shorthand @ -->
    <button @click="handleClick">Click</button>
    <button @click="count++">Count: {{ count }}</button>
    <input @keyup.enter="submit" @keyup.esc="cancel" />
    <form @submit.prevent="handleSubmit">...</form>

    <!-- v-model - two-way binding -->
    <input v-model="text" />
    <p>You typed: {{ text }}</p>

    <!-- v-model modifiers -->
    <input v-model.trim="trimmed" />      <!-- trim whitespace -->
    <input v-model.number="age" type="number" />  <!-- convert to number -->
    <input v-model.lazy="lazy" />         <!-- update on change, not input -->

    <!-- v-once - render once, no reactivity -->
    <p v-once>Initial value: {{ count }}</p>

    <!-- Template with v-if (no extra DOM element) -->
    <template v-if="showGroup">
      <h3>Group Title</h3>
      <p>Group content</p>
    </template>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const role = ref('admin')
const isVisible = ref(true)
const imgSrc = ref('/photo.jpg')
const imgAlt = ref('Photo')
const isRound = ref(true)
const url = ref('https://vuejs.org')
const newTab = ref(true)
const count = ref(0)
const text = ref('')
const trimmed = ref('')
const age = ref(0)
const lazy = ref('')
const showGroup = ref(true)
function handleClick() { alert('Clicked!') }
function submit() { console.log('Submitted') }
function cancel() { console.log('Cancelled') }
function handleSubmit() { console.log('Form submitted') }
</script>

What are Directives? - HTML Example

What are Directives? - HTML Example
<template>
  <div>
    <!-- v-for with array -->
    <ul>
      <li v-for="(item, index) in fruits" :key="index">
        {{ index + 1 }}. {{ item }}
      </li>
    </ul>

    <!-- v-for with objects -->
    <div v-for="user in users" :key="user.id" class="user-card">
      <h3>{{ user.name }}</h3>
      <p>{{ user.email }}</p>
      <span :class="`badge-${user.role}`">{{ user.role }}</span>
    </div>

    <!-- v-for with range -->
    <span v-for="n in 5" :key="n">{{ n }} </span>

    <!-- v-for with object properties -->
    <div v-for="(value, key, index) in person" :key="key">
      {{ index }}. {{ key }}: {{ value }}
    </div>

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

    <!-- Dynamic list operations -->
    <button @click="addUser">Add User</button>
    <button @click="removeUser(0)">Remove First</button>
    <button @click="sortUsers">Sort</button>
  </div>
</template>

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

const fruits = ref(['Apple', 'Banana', 'Cherry'])
const users = reactive([
  { id: 1, name: 'Alice', email: 'alice@example.com', role: 'admin', active: true },
  { id: 2, name: 'Bob',   email: 'bob@example.com',   role: 'user',  active: false },
  { id: 3, name: 'Carol', email: 'carol@example.com', role: 'user',  active: true },
])
const person = reactive({ name: 'Alice', age: 25, city: 'NYC' })

function addUser() {
  users.push({ id: Date.now(), name: 'New User', email: 'new@example.com', role: 'user', active: true })
}
function removeUser(index) { users.splice(index, 1) }
function sortUsers() { users.sort((a, b) => a.name.localeCompare(b.name)) }
</script>

Directive Lifecycle

Directive hooks receive the element, binding, vnode, and previous vnode as appropriate. Initialize DOM resources when mounted, respond to relevant binding changes in updated, and disconnect observers or destroy widgets in unmounted. Store only narrowly required cleanup data on the element or in a private WeakMap.

Treat binding values as untrusted configuration and avoid injecting raw HTML. A directive cannot replace a component when the feature owns markup, state, and events. Register locally unless the behavior is genuinely available throughout the application.

Built-In Directives Express Different Update Rules

v-bind updates an attribute or property, v-on registers an event listener, v-model coordinates value and update events, v-if creates and destroys a branch, and v-show keeps the element while toggling display. Choose from lifecycle and frequency: v-show suits frequent visibility changes, while v-if avoids creating a branch that may never be needed.

v-for needs a stable key when rendered items can move or keep local state. Avoid placing v-if and v-for on the same element because their precedence makes scope and filtering harder to reason about; derive the filtered collection or move the condition to a wrapper.

Arguments, Modifiers, and Dynamic Values

A directive can receive an argument such as href in v-bind:href and modifiers such as prevent or stop in an event directive. Shorthands preserve the same semantics, so @submit.prevent still combines event registration with default-action prevention. Modifier order matters when generated handlers perform operations in sequence.

Dynamic arguments must resolve to a valid name or null and are harder to statically inspect. Prefer explicit bindings when names are known. Treat raw HTML as a trust boundary: v-html inserts HTML and must never receive unsanitized user-controlled content.

Before you move on

Vue Directives v if, v for, v model, v bind Mastery Check

5 checks
  • v-if / v-else-if / v-else means Conditional rendering (removes from DOM); a typical example is -.
  • v-show means Toggle visibility (keeps in DOM); a typical example is -.
  • v-for means Render list; a typical example is -.
  • v-bind means Bind attribute to data; a typical example is.
  • What are Directives? includes Conditional rendering (removes from DOM), Toggle visibility (keeps in DOM), Render list, and Bind attribute to data.
Browse Free Tutorials

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