指令是 Vue 模板语法中的核心特性,它们是以 v-
为前缀的特殊属性,用于在 DOM 元素上应用特殊的响应式行为。下面我将全面解析 Vue 中的指令语法。
v-
前缀开头语法结构:
<HTML标签 v-指令名:参数="表达式">HTML标签>
<element v-directive:argument.modifier="expression">element>
v-if
, v-for
)v-bind:href
).prevent
)v-if
/ v-else-if
/ v-else
<div v-if="score >= 90">优秀div>
<div v-else-if="score >= 60">及格div>
<div v-else>不及格div>
v-show
<div v-show="isVisible">显示内容div>
v-if
vs v-show
特性 | v-if |
v-show |
---|---|---|
渲染方式 | 条件为假时销毁元素 | 使用 CSS display 控制 |
切换开销 | 高(销毁重建组件) | 低(仅切换 CSS 属性) |
初始渲染 | 惰性渲染(条件为真才渲染) | 无论条件如何都渲染 |
使用场景 | 不频繁切换的场景 | 频繁切换的场景 |
v-for
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index + 1 }}. {{ item.name }}
li>
<li v-for="(value, key, index) in user" :key="key">
{{ index }}. {{ key }}: {{ value }}
li>
ul>
key
:为每个节点提供唯一标识v-if
同用:可能导致渲染优先级问题v-bind
<img v-bind:src="imageUrl" alt="图片">
<a :href="url">链接a>
<div :class="{ active: isActive, 'text-danger': hasError }">div>
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }">div>
v-on
<button v-on:click="handleClick">点击button>
<button @click="handleClick">简写形式button>
<button @click="count++">增加计数button>
<button @click="handleEvent('hello', $event)">传递参数button>
methods: {
handleEvent(msg, event) {
console.log(msg, event.target);
}
}
v-model
<input v-model="message" placeholder="输入内容">
<p>输入的内容是: {{ message }}p>
v-model
<CustomInput v-model="searchText" />
<CustomInput
:value="searchText"
@input="searchText = $event"
/>
v-text
<span v-text="message">span>
<span>{{ message }}span>
v-html
<div v-html="rawHtml">div>
安全警告:仅渲染可信内容,防止 XSS 攻击
v-pre
<div v-pre>{{ 这里的内容不会被编译 }}div>
v-once
<span v-once>{{ 只渲染一次的内容 }}span>
v-cloak
<div v-cloak>{{ message }}div>
[v-cloak] {
display: none;
}
// 全局注册
Vue.directive('focus', {
inserted: function (el) {
el.focus()
}
})
// 局部注册
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
}
<input v-focus>
钩子函数 | 调用时机 |
---|---|
bind |
指令第一次绑定到元素时调用 |
inserted |
被绑定元素插入父节点时调用 |
update |
所在组件 VNode 更新时调用 |
componentUpdated |
所在组件及子组件 VNode 全部更新后 |
unbind |
指令与元素解绑时调用 |
<form @submit.prevent="onSubmit">form>
<div @click.stop="doThis">div>
<button @click.once="doThis">button>
<button @click.stop.prevent="doThis">button>
<div @click.capture="doThis">div>
<div @click.self="doThat">div>
<input @keyup.enter="submit">
<input @keyup.page-down="onPageDown">
<input @keyup.13="submit">
<input @keyup.alt.67="clear">
<div @click.ctrl="doSomething">div>
v-model
修饰符
<input v-model.lazy="msg">
<input v-model.number="age" type="number">
<input v-model.trim="msg">
<a v-bind:[attributeName]="url">链接a>
<a v-on:[eventName]="doSomething">操作a>
data() {
return {
attributeName: 'href',
eventName: 'focus'
}
}
v-for
优化
<li v-for="item in items" :key="item.id">li>
<template v-for="item in items">
<div v-if="item.isActive" :key="item.id">div>
template>
// 不推荐
<div>{{ message.split('').reverse().join('') }}</div>
// 推荐
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
// 不推荐
<button @click="fetchData(selectedCategory)">加载</button>
// 推荐:使用函数柯里化
methods: {
fetchData(category) {
return () => {
// 实际获取数据的逻辑
}
}
}
v-if
和 v-for
优先级问题问题:在 Vue 2.x 中,v-for
优先级高于 v-if
解决:
<div v-for="item in activeItems" :key="item.id">div>
<template v-for="item in items">
<div v-if="item.isActive" :key="item.id">div>
template>
问题:直接通过索引修改数组不会触发视图更新
解决:
// 错误
this.items[0] = newValue;
// 正确
this.$set(this.items, 0, newValue);
// 或
this.items.splice(0, 1, newValue);
问题:直接添加新属性不会触发视图更新
解决:
// 错误
this.user.newProperty = 'value';
// 正确
this.$set(this.user, 'newProperty', 'value');
Vue 的指令系统提供了强大的模板功能,使开发者能够声明式地将数据绑定到 DOM。掌握指令语法是 Vue 开发的核心能力:
v-if
, v-show
控制元素显示v-for
渲染数组或对象v-bind
动态绑定属性v-on
监听 DOM 事件v-model
实现表单输入绑定v-text
, v-html
等控制内容显示通过合理使用指令修饰符、动态参数和自定义指令,可以大幅提升开发效率和代码质量。同时注意 Vue 的响应式限制和性能优化点,可以构建更健壮的 Vue 应用。