Vue Directives
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 | — |
<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>
<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>
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.