Vue3 指令介绍
Vue 指令(Directives)是 Vue.js 的一项核心功能,它们可以在 HTML 模板中以 v- 开头的特殊属性形式使用,用于将响应式数据绑定到 DOM 元素上或在 DOM 元素上进行一些操作。
Vue 指令是带有前缀 v- 的特殊 HTML 属性,它赋予 HTML 标签额外的功能。
与传统的 JavaScript 方法相比,使用 Vue 创建响应式页面要容易得多,并且需要的代码更少。
常用指令:
| 指令 | 描述 |
v-bind |
用于将 Vue 实例的数据绑定到 HTML 元素的属性上。 |
v-if |
用于根据表达式的值来条件性地渲染元素或组件。 |
v-show |
v-show 是 Vue.js 提供的一种指令,用于根据表达式的值来条件性地显示或隐藏元素。 |
v-for |
用于根据数组或对象的属性值来循环渲染元素或组件。 |
v-on |
用于在 HTML 元素上绑定事件监听器,使其能够触发 Vue 实例中的方法或函数。 |
v-model |
用于在表单控件和 Vue 实例的数据之间创建双向数据绑定。 |
除了这些常用的指令,Vue 还提供了一些其他的指令,如 v-text、v-html 等,以及自定义指令,让开发者能够更加灵活地操作 DOM 元素。
一、属性绑定与事件绑定
1.属性绑定 (v-bind)
1.1基本概念
属性绑定是 Vue.js 的核心功能之一,通过 v-bind 指令实现数据到 HTML 属性的动态绑定,使属性值能够响应式更新。
1.2基本语法
<!-- 完整语法 -->
<img v-bind:src="imageSrc">
<!-- 简写语法 -->
<img :src="imageSrc">
1.3绑定到 class 属性
对象语法
通过对象动态切换 class,对象的键是类名,值是布尔值表达式:
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
对应的数据:
javascript
data() {
return {
isActive: true,
hasError: false
}
}
数组语法
应用多个 class,数组中可以包含数据属性、对象或计算属性:
<div :class="[activeClass, errorClass]"></div>
对应的数据:
javascript
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
1.4绑定到 style 属性
对象语法
样式对象中的属性可以使用驼峰式或短横线分隔:
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
对应的数据:
javascript
data() {
return {
activeColor: 'red',
fontSize: 30
}
}
数组语法
将多个样式对象应用到同一个元素:
<div :style="[baseStyles, overridingStyles]"></div>
1.5绑定其他属性
属性绑定不仅限于 class 和 style,可以绑定到任何 HTML 属性:
<!-- 绑定 disabled 属性 -->
<button :disabled="isButtonDisabled">按钮</button>
<!-- 绑定动态属性名 -->
<div :[attributeName]="attributeValue"></div>
2.事件绑定 (v-on)
2.1基本概念
事件绑定通过 v-on 指令实现,用于监听 DOM 事件并执行相应的 JavaScript 代码。
2.2基本语法
<!-- 完整语法 -->
<button v-on:click="handleClick">点击</button>
<!-- 简写语法 -->
<button @click="handleClick">点击</button>
2.3事件处理方法
内联处理器
<button @click="count++">增加 {{ count }}</button>
方法处理器
<button @click="greet">问候</button>
对应的 JavaScript:
javascript
methods: {
greet(event) {
// event 是原生 DOM 事件
alert('Hello!')
console.log(event.target.tagName)
}
}
传递参数
<button @click="say('hello', $event)">说 hello</button>
对应的 JavaScript:
javascript
methods: {
say(message, event) {
// 访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}<button @click="say('hello', $event)">说 hello</button>
对应的 JavaScript:
javascript
methods: {
say(message, event) {
// 访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}
2.4事件修饰符
事件修饰符是以点开头的特殊后缀,用于指示指令应该以特殊方式绑定:
.stop
阻止事件冒泡:
<a @click.stop="doThis"></a>
.prevent
阻止默认行为:
<form @submit.prevent="onSubmit"></form>
.capture
使用事件捕获模式:
<div @click.capture="doThis">...</div>
.self
只当事件是从侦听器绑定的元素本身触发时才触发回调:
<div @click.self="doThat">...</div>
.once
只触发一次:
<button @click.once="doThis"></button>
.passive
不阻止事件的默认行为,主要用于移动端性能优化:
<div @scroll.passive="onScroll">...</div>
2.5按键修饰符
用于监听特定键盘事件:
<!-- 只有在 key 是 Enter 时调用 vm.submit() -->
<input @keyup.enter="submit">
<!-- 处理 Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
常用按键修饰符:
.enter - 捕获"回车"键
.tab - 捕获"制表符"键
.delete - 捕获"删除"和"退格"键
.esc - 捕获"ESC"键
.space - 捕获"空格"键
.up - 捕获"上箭头"键
.down - 捕获"下箭头"键
.left - 捕获"左箭头"键
.right - 捕获"右箭头"键
二、条件与循环操作指令
1.条件指令
1.1v-if
工作原理:
- v-if 是"真正"的条件渲染,在切换过程中条件块内的事件监听器和子组件会被销毁和重建
- 当条件为 false 时,元素完全从 DOM 中移除
- 支持 v-else-if 和 v-else 链式条件判断
性能特点:
- 初始渲染条件为 false 时,不进行任何渲染操作
- 切换开销较大,因为涉及 DOM 的添加和删除
<!-- 基础用法 -->
<div v-if="isVisible">可见内容</div>
<!-- 条件链 -->
<div v-if="type === 'A'">类型A</div>
<div v-else-if="type === 'B'">类型B</div>
<div v-else>其他类型</div>
<!-- 在 template 上使用 -->
<template v-if="showMultiple">
<p>段落1</p>
<p>段落2</p>
</template>
1.2v-show
工作原理:
- 元素始终会被渲染并保留在 DOM 中
- 通过切换 CSS 的 display 属性来控制显示/隐藏
- 不支持 <template> 元素
性能特点:
- 初始渲染成本较高,无论条件如何都会渲染
- 切换开销小,仅修改 CSS 属性
<div v-show="isActive">显示内容</div>
1.3使用场景对比
| 场景 | 推荐指令 | 理由 |
|---|---|---|
| 运行时很少改变的条件 | v-if |
避免不必要的初始渲染 |
| 频繁切换显示状态 | v-show |
切换性能更好 |
| 需要条件链判断 | v-if |
支持 else-if 和 else |
| 初始状态多为隐藏 | v-if |
减少初始 DOM 节点 |
2.循环指令
2.1v-for
遍历数组:
<!-- 基本数组遍历 -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- 带索引的遍历 -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.name }}
</li>
</ul>
遍历对象:
<!-- 对象属性遍历 -->
<ul>
<li v-for="(value, key) in userObject" :key="key">
{{ key }}: {{ value }}
</li>
</ul>
<!-- 带索引的对象遍历 -->
<ul>
<li v-for="(value, key, index) in userObject" :key="key">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul>
遍历数值范围:
<!-- 从1开始到指定数字 -->
<span v-for="n in 5" :key="n">{{ n }} </span>
<!-- 输出:1 2 3 4 5 -->
2.1:key 属性的重要性
为什么需要 key:
- 帮助 Vue 识别节点的唯一性
- 优化虚拟 DOM 的 diff 算法
- 维持组件状态和临时 DOM 状态
key 的选择原则:
- 使用唯一标识符(如 id)
- 避免使用索引作为 key(除非列表静态)
- 确保 key 的稳定性
<!-- 好的实践 -->
<div v-for="user in users" :key="user.id">
{{ user.name }}
</div>
<!-- 避免的做法 -->
<div v-for="(user, index) in users" :key="index">
{{ user.name }}
</div>
2.3数组更新检测
响应式数组方法:
Vue 包装了以下数组方法,调用时会触发视图更新:push() - 末尾添加、pop() - 删除末尾、shift() - 删除开头、unshift() - 开头添加、splice() - 删除/添加、sort() - 排序、reverse() - 反转
// 这些操作会触发视图更新
this.items.push(newItem)
this.items.splice(0, 1) // 删除第一个元素
注意事项:
- 直接通过索引修改不会触发更新:this.items[0] = newValue
- 使用 Vue.set 或数组的 splice 方法解决
三、表单的双向绑定
1. v-model 基础概念
1.1 什么是 v-model
v-model 是 Vue 中用于实现表单元素和数据之间双向绑定的指令。当表单元素的值发生变化时,数据会自动更新;当数据发生变化时,表单元素的值也会相应更新。
1.2 v-model 的本质
v-model 实际上是语法糖,它结合了属性绑定和事件监听:
<!-- 以下两种写法是等价的 -->
<input v-model="message">
<input :value="message" @input="message = $event.target.value">
2. 不同类型表单元素的使用
2.1 文本输入框
单行文本输入框:
<input type="text" v-model="username">
多行文本域:
<textarea v-model="description"></textarea>
2.2 复选框
单个复选框:
绑定到布尔值,表示是否选中
<input type="checkbox" v-model="agree">
多个复选框:
绑定到数组,包含所有选中项的 value 值
<input type="checkbox" value="vue" v-model="skills">
<input type="checkbox" value="react" v-model="skills">
2.3 单选按钮
绑定到同一个变量,选中的按钮的 value 值会赋给该变量
<input type="radio" value="male" v-model="gender">
<input type="radio" value="female" v-model="gender">
2.4 选择框
单选下拉框:
绑定到选中的 option 的 value
<select v-model="selectedCity">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
</select>
多选下拉框:
绑定到数组,包含所有选中项的 value
<select v-model="selectedHobbies" multiple>
<option value="reading">阅读</option>
<option value="sports">运动</option>
</select>
3. v-model 修饰符
3.1 .lazy 修饰符
默认情况下,v-model 在 input 事件发生后同步数据。使用 .lazy 修饰符后,改为在 change 事件后同步。
<!-- 输入时不会立即更新,失去焦点时才更新 -->
<input v-model.lazy="message">
3.2 .number 修饰符
自动将用户输入的值转换为数字类型。如果无法解析,则返回原始值。
<input v-model.number="age" type="number">
3.3 .trim 修饰符
自动过滤用户输入的首尾空白字符。
<input v-model.trim="username">
4. 自定义组件中的 v-model
4.1 Vue3 中的变化
Vue3 对自定义组件的 v-model 进行了重大改进:
Vue3 中的写法:
<CustomComponent v-model="pageTitle" />
等价于:
<CustomComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event" />
4.2 在自定义组件中实现 v-model
子组件:
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
>
</template>
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
4.3 多个 v-model 绑定
Vue3 支持在单个组件上使用多个 v-model:
<UserName
v-model:first-name="first"
v-model:last-name="last"
/>
对应的子组件:
<template>
<input
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"
>
<input
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"
>
</template>
<script>
export default {
props: {
firstName: String,
lastName: String
},
emits: ['update:firstName', 'update:lastName']
}
</script>
5. 自定义修饰符
5.1 创建自定义修饰符
可以为组件的 v-model 添加自定义修饰符:
<MyComponent v-model.capitalize="myText" />
在组件中处理修饰符:
<script>
export default {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
methods: {
emitValue(e) {
let value = e.target.value
if (this.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
this.$emit('update:modelValue', value)
}
}
}
</script>
6. 实际应用注意事项
6.1 初始值设置
确保为 v-model 绑定的数据提供适当的初始值:
data() {
return {
// 文本输入框
username: '',
// 单个复选框
agree: false,
// 多个复选框
skills: [],
// 单选按钮
gender: '',
// 下拉选择
selectedCity: ''
}
}
6.2 性能考虑
-
对于大型表单,考虑使用 .lazy 修饰符减少更新频率
-
复杂表单建议使用 Vuex 或 Pinia 进行状态管理
6.3 表单验证
v-model 可以结合表单验证库使用,如 VeeValidate、Vuelidate 等,实现更强大的表单功能。
通过掌握这些 v-model 的使用技巧,可以更高效地处理 Vue3 应用中的表单交互,提升开发效率和用户体验。
更多推荐



所有评论(0)