香网小说
23.08MB · 2025-09-30
Vue.js 是一个用于构建用户界面的渐进式框架,而指令(Directives) 是 Vue 的核心特性之一。它们是以 v-
开头的特殊属性,用于在 DOM 上绑定行为,实现数据与视图的自动同步。
本文将带你全面掌握 Vue 3 中最常用的内置指令,深入理解其工作原理,并通过实际案例揭示常见陷阱与最佳实践。
Vue 指令是带有 v-
前缀的特殊 HTML 属性,用于在元素上应用响应式的行为。当指令的值发生变化时,DOM 会自动更新。
<p v-if="visible">这是一段条件渲染的内容</p>
v-model
:双向数据绑定v-model
是表单元素中最常用的指令,实现数据 ↔ 视图的双向绑定。
<template>
<input v-model="message" placeholder="输入内容" />
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('Hello Vue')
</script>
支持类型:input
、textarea
、select
、组件(支持 .trim
、.number
修饰符)
v-if
/ v-else
/ v-else-if
vs v-show
:条件控制但从底层实现来看,它们的工作方式完全不同。
v-if
是“动真格”的销毁,v-show
是“穿隐身衣”特性 | v-if | v-show |
---|---|---|
渲染机制 | 条件为假时不渲染到 DOM 中(完全移除) | 始终渲染,通过 display: none 控制隐藏 |
切换开销 | 高(每次切换都要创建/销毁节点) | 低(只是切换 CSS) |
初始渲染性能 | 快(不满足条件不渲染) | 稍慢(始终渲染) |
适用场景 | 条件很少变化 | 频繁切换显示状态 |
<!-- v-if:元素可能不存在 -->
<div v-if="isVisible">我可能会被删除</div>
<!-- v-show:元素一直存在,只是藏起来了 -->
<div v-show="isVisible">我一直在这里,只是看不见</div>
建议:
v-if
v-show
v-for
:列表渲染与 key
的重要性v-for
用于基于数组或对象渲染列表。
<template>
<ul>
<li v-for="(item, index) in items" :key="index">
{{ item.name }}
</li>
</ul>
</template>
但如果你只用 index
作为 key
,可能会引发严重的状态错乱问题!
key
导致勾选项错位假设我们有一个待办事项列表,用户可以勾选已完成项:
<template>
<div>
<button @click="addItem">添加新任务</button>
<ul>
<li v-for="(task, index) in tasks" :key="index">
<input type="checkbox" v-model="task.done" />
{{ task.text }}
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue'
const tasks = ref([
{ text: '学习 Vue', done: false },
{ text: '写代码', done: true }, // 已勾选
{ text: '休息', done: false }
])
const addItem = () => {
tasks.value.unshift({ text: '新任务', done: false })
}
</script>
因为 :key="index"
导致 Vue 的虚拟 DOM diff 算法出现误判:
Vue 认为:
index=0
的节点现在变成了 “新任务”index=1
的节点现在变成了 “学习 Vue”但它复用了原来的 DOM 节点,包括 input 的 checked
状态!
所以,“学习 Vue” 这个新位置的节点继承了原来 “写代码” 的勾选状态 —— 状态错乱!
key
const tasks = ref([
{ id: 1, text: '学习 Vue', done: false },
{ id: 2, text: '写代码', done: true },
{ id: 3, text: '休息', done: false }
])
<li v-for="task in tasks" :key="task.id">
<input type="checkbox" v-model="task.done" />
{{ task.text }}
</li>
此时 Vue 能准确识别每个任务的身份,无论顺序如何变化,勾选状态都会正确保留。
结论:永远不要用 index
作为 key
,除非列表是静态且永不排序/增删。
v-on
(简写 @
):事件绑定绑定 DOM 事件,触发 JavaScript 方法。
<template>
<button @click="handleClick">点击我</button>
<input @keyup.enter="onEnter" />
</template>
<script setup>
const handleClick = () => {
alert('按钮被点击!')
}
const onEnter = () => {
console.log('按下了回车')
}
</script>
支持修饰符:.stop
、.prevent
、.once
、.self
等。
v-bind
(简写 :
):属性绑定动态绑定 HTML 属性或组件 prop。
<template>
<img :src="imageSrc" :alt="description" />
<a :href="url" :class="{ active: isActive }">链接</a>
<MyComponent :title="title" />
</template>
支持绑定:class
、style
、href
、src
、自定义 prop 等。
v-text
和 v-html
:更新文本与 HTMLv-text
:更新元素的 textContent
v-html
:更新 innerHTML
(️ 注意 XSS 风险)<template>
<p v-text="plainText"></p>
<div v-html="htmlContent"></div>
</template>
v-pre
和 v-once
:性能优化v-pre
:跳过编译过程,直接输出原始模板。v-once
:只渲染一次,后续更新不再触发。<template>
<span v-pre>{{ 这不会被编译 }}</span>
<p v-once>{{ msg }}</p>
</template>
适用于静态内容,提升性能。
除了内置指令,Vue 3 还支持自定义指令,用于处理底层 DOM 操作。
v-focus
指令// main.js
app.directive('focus', {
mounted(el) {
el.focus()
}
})
使用:
<input v-focus />
常见用途:自动聚焦、懒加载图片、权限控制等。
实践 | 建议 |
---|---|
v-for 配合 :key | 必须加,优先使用唯一 ID,避免用 index |
v-if vs v-show | 根据使用频率选择:少变用 v-if ,常变用 v-show |
v-model 修饰符 | 善用 .trim 、.number 提高用户体验 |
事件修饰符 | .prevent 、.stop 很实用 |
自定义指令 | 封装通用 DOM 操作逻辑 |
Vue 3 的指令系统简洁而强大,是实现响应式 UI 的核心工具。掌握这些指令不仅能提升开发效率,更能帮助你写出健壮、可维护的代码。
尤其是 v-if
与 v-show
的选择、v-for
中 key
的正确使用,往往决定了应用的稳定性与用户体验。
现在,就去检查你的代码,确保每一个 v-for
都有正确的 key
吧!
延伸阅读: