在 Vue 中,指令(Directive) 是带有 v- 前缀的特殊 HTML 特性,用来响应式地修改 DOM 。Vue 3 中指令分为 内置指令 、自定义指令,以及配合 Composition API 的新用法。
一、Vue 3 常见内置指令
1️⃣ 条件渲染
vue
<div v-if="isVisible">显示</div>
<div v-else-if="loading">加载中</div>
<div v-else>隐藏</div>
<div v-show="isVisible">切换显示</div>
| 指令 | 区别 |
|---|---|
v-if |
真正的条件渲染(销毁 / 重建 DOM) |
v-show |
仅切换 display CSS |
2️⃣ 列表渲染
vue
<ul>
<li v-for="(item, index) in list" :key="item.id">
{{ index }} - {{ item.name }}
</li>
</ul>
✅ 必须加 :key
3️⃣ 事件绑定
vue
<button @click="handleClick">点击</button>
<button @click.stop="stopPropagation">阻止冒泡</button>
<button @click.prevent="submit">阻止默认</button>
<button @click.once="onlyOnce">只触发一次</button>
@ 是 v-on: 的简写
4️⃣ 双向绑定
vue
<input v-model="name" />
<!-- 等价写法 -->
<input :value="name" @input="name = $event.target.value" />
修饰符:
vue
<input v-model.trim="name" />
<input v-model.number="age" />
<input v-model.lazy="msg" />
5️⃣ 属性绑定
vue
<img :src="imgUrl" />
<div :class="{ active: isActive }"></div>
<div :style="{ color: textColor }"></div>
6️⃣ 文本插值 & HTML
vue
<span>{{ message }}</span>
<span v-text="message"></span>
<span v-html="htmlContent"></span>
⚠️ v-html 有 XSS 风险
7️⃣ 其他常用指令
vue
<div v-pre>{{ 不会被编译 }}</div>
<div v-cloak>{{ 防止闪屏 }}</div>
<div v-once>只渲染一次</div>
二、自定义指令(Vue 3)
1️⃣ 全局注册
js
// main.js
app.directive('focus', {
mounted(el) {
el.focus()
}
})
vue
<input v-focus />
2️⃣ 局部注册
vue
<script setup>
const vFocus = {
mounted(el) {
el.focus()
}
}
</script>
<template>
<input v-focus />
</template>
3️⃣ 指令钩子(Vue 3)
js
app.directive('example', {
created(el) {},
beforeMount(el) {},
mounted(el) {},
beforeUpdate(el) {},
updated(el) {},
beforeUnmount(el) {},
unmounted(el) {}
})
4️⃣ 带参数的指令
vue
<p v-color="'red'">文字变红</p>
js
app.directive('color', {
mounted(el, binding) {
el.style.color = binding.value
},
updated(el, binding) {
el.style.color = binding.value
}
})
5️⃣ 修饰符支持
vue
<input v-format.limit10 />
js
app.directive('format', {
mounted(el, binding) {
if (binding.modifiers.limit10) {
el.maxLength = 10
}
}
})
三、常用自定义指令示例
✅ 防抖指令
js
app.directive('debounce', {
mounted(el, binding) {
let timer
el.addEventListener('click', () => {
clearTimeout(timer)
timer = setTimeout(() => {
binding.value()
}, 500)
})
}
})
vue
<button v-debounce="submit">提交</button>
✅ 权限指令
js
app.directive('permission', {
mounted(el, binding) {
const hasPerm = checkPermission(binding.value)
if (!hasPerm) {
el.parentNode?.removeChild(el)
}
}
})
vue
<button v-permission="'user:add'">新增用户</button>
四、指令 vs 组件
| 场景 | 推荐 |
|---|---|
| DOM 行为(焦点、拖拽、权限) | 指令 |
| UI + 逻辑复用 | 组件 |
| 表单交互 | v-model / 组件 |
五、Vue 3 指令变化总结
✅ 生命周期改为 挂载/更新/卸载
✅ 支持 v-bind / v-on 动态参数
✅ 更适合与 Composition API 结合