一、Vue 内置指令大全
1. v-bind
:动态绑定属性
用于动态绑定 HTML 属性或组件 prop。
html
<!-- 绑定 class -->
<div v-bind:class="{ active: isActive }"></div>
<!-- 缩写 -->
<img :src="imageURL" :alt="title">
<!-- 绑定对象 -->
<a v-bind="{ href, target, rel }">链接</a>
✅ 支持所有 HTML 属性和组件 prop。
2. v-model
:双向数据绑定
简化表单元素与数据的同步。
html
<input v-model="message" placeholder="双向绑定">
<p>输入内容:{{ message }}</p>
<!-- 修饰符 -->
<input v-model.trim="username" />
<input v-model.number="age" />
<input v-model.lazy="search" />
🔁
v-model
是:value
+@input
的语法糖。
3. v-on
:事件监听
绑定 DOM 事件。
html
<button v-on:click="handleClick">点击</button>
<!-- 缩写 -->
<button @click="save">保存</button>
<!-- 修饰符 -->
<form @submit.prevent="onSubmit">
<input @keyup.enter="search" />
<button @click.once="doOnce">只触发一次</button>
✅ 常用修饰符:
.prevent
,.stop
,.once
,.self
,.enter
,.tab
等。
4. v-if
/ v-else
/ v-else-if
:条件渲染
根据表达式真假决定是否渲染 DOM。
html
<div v-if="type === 'A'">类型 A</div>
<div v-else-if="type === 'B'">类型 B</div>
<div v-else>其他</div>
⚠️ 与
v-show
区别:v-if
是"真正"渲染/销毁,v-show
是display: none
控制。
5. v-show
:显示/隐藏切换
通过 CSS 控制显示状态。
html
<div v-show="isVisible">我被 v-show 控制</div>
✅ 适用于频繁切换的场景。
6. v-for
:列表渲染
基于数组或对象渲染列表。
html
<li v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.name }}
</li>
<!-- 遍历对象 -->
<li v-for="(value, key) in user" :key="key">
{{ key }}: {{ value }}
</li>
✅ 必须使用
:key
提升性能与稳定性。
7. v-cloak
:防止闪现
解决页面加载时 Vue 未初始化导致的 {``{ message }}
闪现问题。
html
<style>
[v-cloak] { display: none; }
</style>
<div v-cloak>{{ message }}</div>
✅ 配合 CSS 使用,Vue 实例挂载后自动移除。
8. v-pre
和 v-once
v-pre
:跳过该元素及其子元素的编译过程。v-once
:仅渲染一次,后续更新不重新渲染。
html
<span v-pre>{{ this will not be compiled }}</span>
<span v-once>{{ msg }}</span> <!-- msg 变化也不会更新 -->
✅ 用于静态内容或性能优化。
二、自定义指令:扩展 Vue 能力
当内置指令无法满足需求时,我们可以创建自定义指令。
1. 注册方式
全局注册
javascript
// main.js
import { createApp } from 'vue'
const app = createApp({})
app.directive('focus', {
mounted(el) {
el.focus()
}
})
局部注册
html
<script>
export default {
directives: {
focus: {
mounted(el) {
el.focus()
}
}
}
}
</script>
2. 钩子函数(生命周期)
钩子 | 触发时机 |
---|---|
created |
指令绑定前 |
beforeMount |
元素挂载前 |
mounted |
元素插入父节点后(常用) |
beforeUpdate |
组件更新前 |
updated |
组件更新后 |
beforeUnmount |
元素卸载前 |
unmounted |
元素卸载后(清理事件监听) |
3. 钩子函数参数
每个钩子接收以下参数:
javascript
app.directive('demo', {
mounted(el, binding, vnode, prevVnode) {
// el: 指令绑定的元素
// binding: 指令信息对象
// binding.value: 传入的值
// binding.arg: 参数,如 v-demo:arg
// binding.modifiers: 修饰符,如 v-demo.foo.bar
// vnode: 虚拟节点
// prevVnode: 上一个虚拟节点(更新时)
}
})
三、自定义指令实战案例
案例 1:自动聚焦(v-focus)
javascript
app.directive('focus', {
mounted(el) {
el.focus()
}
})
html
<input v-focus placeholder="页面加载后自动聚焦">
案例 2:权限控制(v-permission)
javascript
// 假设用户权限存储在全局 store 或 config 中
const userPermissions = ['create', 'edit']
app.directive('permission', {
mounted(el, binding) {
const requiredPerm = binding.value
if (!userPermissions.includes(requiredPerm)) {
el.parentNode.removeChild(el) // 移除无权限的按钮
// 或 el.style.display = 'none'
}
}
})
html
<button v-permission="'create'">新建用户</button>
<button v-permission="'delete'">删除用户</button> <!-- 会被移除 -->
✅ 企业级应用中常见需求。
案例 3:防重复点击(v-debounce)
javascript
let timer = null
app.directive('debounce', {
mounted(el, binding) {
const delay = binding.value || 1000
el.addEventListener('click', () => {
if (timer) return
binding.instance[binding.arg] && binding.instance[binding.arg]()
timer = setTimeout(() => {
timer = null
}, delay)
})
}
})
html
<template>
<button v-debounce:submit="1000">提交</button>
</template>
<script>
export default {
methods: {
submit() {
console.log('表单提交')
// 发送请求
}
}
}
</script>
✅ 防止用户多次点击造成重复提交。
案例 4:图片懒加载(v-lazy)
javascript
const imgObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target
img.src = img.dataset.src
imgObserver.unobserve(img)
}
})
})
app.directive('lazy', {
mounted(el, binding) {
el.dataset.src = binding.value
el.src = 'placeholder.jpg' // 占位图
imgObserver.observe(el)
},
unmounted(el) {
imgObserver.unobserve(el)
}
})
html
<img v-lazy="imageUrl" alt="懒加载图片">
✅ 提升首屏加载性能。
四、Vue 3 Composition API 中的指令
在 setup()
中注册局部指令:
html
<script>
import { ref } from 'vue'
export default {
setup() {
const vFocus = {
mounted: (el) => el.focus()
}
const count = ref(0)
return {
vFocus,
count
}
}
}
</script>
<template>
<input v-focus>
</template>
五、最佳实践与注意事项
✅ 推荐做法
- 优先使用组件而非指令:指令应专注于 DOM 操作。
- 复杂逻辑封装为 composables:避免指令过于臃肿。
- 及时清理资源 :在
unmounted
中移除事件监听、定时器等。 - 命名语义化 :如
v-permission
,v-debounce-click
。
❌ 避免
- 在指令中修改组件状态(
binding.instance
不稳定) - 过度使用全局指令,造成命名污染
- 忽略响应式更新(
updated
钩子)
六、总结
类型 | 指令 | 用途 |
---|---|---|
内置指令 | v-bind , v-model , v-on |
数据绑定与事件 |
v-if , v-show |
条件渲染 | |
v-for |
列表渲染 | |
v-cloak , v-pre |
编译控制 | |
自定义指令 | v-focus , v-permission |
扩展 DOM 能力 |
v-debounce , v-lazy |
复用交互逻辑 |
📌 核心思想:内置指令解决通用问题,自定义指令解决特定场景的 DOM 操作。
七、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!