指令
插值语法
mustache
mustache:{ {variable} }
,最基础的数据绑定方式,用于将数据动态渲染为纯文本内容。
语法:
html<div>{{ variable }}</div>
示例:
html<script> data() { return { message: "Hello Vue!", count: 42 }; } </script> <div>{{ message }}</div> <!-- 输出:Hello Vue! --> <div>{{ count }}</div> <!-- 输出:42 -->
特性:
响应式:数据变化时,插值内容会自动更新。
支持JS表达式:
html<!-- 1. 算术运算 --> <div>{{ count + 1 }}</div> <!-- 输出:43 --> <div>{{ count * 2 }}</div> <!-- 输出:84 --> <!-- 2. 三元运算符 --> <div>{{ count > 0 ? '正数' : '零或负数' }}</div> <!-- 输出:正数 --> <!-- 3. 方法调用(不推荐) --> <div>{{ message.toUpperCase() }}</div> <!-- 输出:HELLO VUE! --> <!-- 4. 访问对象或数组 --> <div>{{ user.name }}</div> <!-- 输出:Alice --> <div>{{ list[0] }}</div> <!-- 输出:Apple -->
不支持语句和声明:
html<!-- 1. 不支持变量声明 --> <h2>{{var name = "Hello"}}</h2> <!-- 错误用法 --> <!-- 2. 不支持流程控制语句if --> <h2>{{ if (true) { return message } }}</h2> <!-- 错误用法 -->
HTML转义:mustache语法会将内容中的HTML标签自动转义为纯文本,避免 XSS 攻击。
html<div><span>危险内容</span></div> <!-- 转义后结果 -->
不能用于HTML属性:mustache语法不能直接用于HTML属性,需改用 v-bind。
html<div id="{{ dynamicId }}"></div> <!-- 错误用法 --> <div v-bind:id="dynamicId"></div> <!-- 正确用法 -->
不推荐方法调用:mustache中调用方法是合法的,但是只推荐逻辑简单且无副作用的方法,复杂逻辑的方法推荐使用computed计算属性。
html<div>{{ reversedMessage }}</div> <!-- 输出:!euV olleH -->
jscomputed: { reversedMessage() { return this.message.split('').reverse().join(''); } }
结合过滤器:
- 在 Vue2 中,可通过过滤器格式化内容。
- 在 Vue3 中已经废弃了过滤器,推荐使用计算属性或方法。
html<div>{{ message | capitalize }}</div>
jsfilters: { capitalize(value) { return value.charAt(0).toUpperCase() + value.slice(1); } }
空白内容处理:如果绑定的值为 null 或 undefined,Mustache 会渲染为空字符串。
html<div>{{ undefinedValue }}</div> <!-- 输出空白 -->
闪烁问题:在未编译完成时,原始
{ { } }
可能短暂显示。可以添加v-cloak
并通过 CSS 隐藏未编译的模板。html<div v-cloak>{{ message }}</div>
css[v-cloak] { display: none; }
文本渲染
v-text
v-text:dataProperty
,用于将数据作为纯文本动态渲染到元素中。
dataProperty:
基本类型
,绑定的数据可以是字符串、数字或其他基本类型,非字符串类型会自动转换为字符串。示例:
html<div v-text="message"></div> <!-- 输出:Hello Vue! --> <div v-text="count"></div> <!-- 输出:42 -->
jsdata() { return { message: "Hello Vue!", // 字符串 count: 42 // 数字 }; }
特性:
覆盖行为:
- v-text 会替换目标元素的全部内容,包括子元素。
- Mustache 仅替换插值标记位置的内容。
html<!-- 1. 使用 v-text --> <div v-text="content">原始内容会被覆盖</div> <!-- 渲染结果:<div>动态内容</div> --> <!-- 2. 使用 Mustache --> <div>原始内容 {{ dynamicPart }} 保留</div> <!-- 渲染结果:<div>原始内容 动态部分 保留</div> -->
转义行为:
- v-text 会将内容中的 HTML 标签转义为纯文本,防止 XSS 攻击。
- v-html 会解析数据中的 HTML 标签并渲染。
html<div><script>alert(1)</script></div> <!-- v-text转义后结果 -->
动态绑定:可绑定计算属性、方法返回值或复杂表达式。
html<div v-text="message.toUpperCase()"></div> <!-- 方法 --> <div v-text="user.name + '的年龄:' + user.age"></div> <!-- 表达式 -->
闪烁问题:v-text 不存在闪烁问题。
性能优化:对于复杂逻辑,优先使用计算属性而非直接在模板中调用方法。
html<!-- 推荐 --> <div v-text="formattedDate"></div> <!-- 不推荐 --> <div v-text="formatDate(timestamp)"></div>
指令冲突:避免在同一元素上同时使用 v-text 和 v-html,或与其他内容类指令混用。
v-html
v-html:dataProperty
,用于将数据作为原始 HTML 解析并渲染到元素中。
dataProperty:
HTMLString
,包含有效的 HTML 的字符串。语法:
html<div v-html="rawHtml"></div>
示例:
html<!-- 模板中使用 --> <div v-html="rawHtml"></div> <!-- Vue 实例或组件 --> <script> data() { return { rawHtml: '<span style="color: red;">红色文字</span>' }; } </script> <!-- 渲染结果 --> <div> <span style="color: red;">红色文字</span> </div>
特性:
对比mustache:
- mustache 会将数据解释为纯文本,直接输出 HTML 标签的源代码。
- v-html 会解析数据中的 HTML 标签并渲染。
html<div><span style="color: red;">红色文字</span></div> <!-- mustache渲染结果 --> <div><span style="color: red;">红色文字</span></div> <!-- v-html渲染结果 -->
动态绑定:v-html 可以绑定动态值,如计算属性、方法返回值等。
html<div v-html="dynamicHTML"></div> <script> computed: { dynamicHTML() { return this.isError ? '<p class="error">错误信息</p>' : '<p>正常信息</p>'; } } </script>
XSS攻击:
v-html 会直接渲染任意 HTML,如果内容来自用户输入或不可信来源,可能导致XSS跨站脚本攻击。需仅渲染可信内容,如后端返回的已消毒的富文本。
html<div v-html="userProvidedContent"></div> <!-- 危险! -->
替代方案:如果需要渲染部分用户输入,可以使用第三方库DOMPurify消毒。
jsimport DOMPurify from 'dompurify'; data() { return { userContent: DOMPurify.sanitize(untrustedHTML) }; }
指令冲突:避免在同一元素上同时使用 v-text 和 v-html,或与其他内容类指令混用。
v-pre
v-pre:空
,用于跳过指定元素及其子元素的编译过程,直接保留原始内容。
语法:
html<div v-pre> <!-- 内部内容不会被 Vue 编译 --> </div>
示例:
html<template> <div> <!-- 使用 v-pre 展示源码 --> <pre v-pre> <div>{{ message }}</div> <button @click="show = true">显示</button> </pre> </div> </template>
特性:
跳过编译:
- v-pre 会跳过元素及其所有子元素的 Vue 模板编译过程,直接保留原始内容。
- 即使内容包含 Vue 语法,如
{ { } }
或指令,也会直接显示为文本。
作用范围:v-pre 会影响整个元素及其子元素,无法局部禁用编译。若需部分跳过编译,需拆分元素结构。
与动态内容冲突:在 v-pre 区域内,所有 Vue 功能如数据绑定、指令均失效。
性能影响:仅在需要时使用 v-pre,过度使用可能导致模板编译优化机会减少。
绑定
v-bind
v-bind:表达式
,用于动态绑定HTML属性、组件prop或DOM属性到Vue实例的数据。
语法:
html<!-- 绑定单个属性 --> <div v-bind:属性名="表达式"></div> <!-- 简写形式(推荐) --> <div :属性名="表达式"></div>
示例:
html<a :href="url">Vue 官网</a> <button :disabled="!isActive">提交</button>
特性:
动态参数:
绑定动态参数:通过
[]
语法动态指定绑定的属性名。html<div :[attrName]="123"></div> <!-- 渲染结果:<div data-id="123"></div> -->
jsdata() { return { attrName: "data-id" } }
动态参数限制:动态属性名需为字符串,且避免使用大写或特殊字符(空格/引号)。当使用DOM内嵌模板(直接写在HTML文件里的模板),浏览器会强制将其转换为小写。
html<!-- 错误示例 --> <div :[dynamicAttr]="value"></div> <!-- HTML模板中会被转换为:[dynamicattr] -->
批量绑定属性:直接绑定一个对象,键为属性名,值为对应数据。
html<div v-bind="attrs"></div> <!-- 渲染结果:<div id="container" class="main" data-status="active"></div> -->
jsdata() { return { attrs: { id: "container", class: "main", "data-status": "active" } }; }
绑定class:
对象语法:根据条件动态切换类名。
html<div :class="{ active: isActive, 'text-red': hasError }"></div>
数组语法:绑定多个类名。
html<div :class="[baseClass, isActive ? 'active' : '']"></div>
绑定style:
对象语法:绑定内联样式对象。CSS属性名可以是camelCase,也可以是kebab-case的写法。
html<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div>
数组语法:应用多个样式对象。CSS属性名可以是camelCase,也可以是kebab-case的写法。
html<div :style="[baseStyles, overrides]"></div>
组件prop传递:在组件上使用v-bind可批量传递props。
html<child-component v-bind="propsObj"></child-component>
Vue3变化:
移除
.sync
修饰符:Vue3中废弃.sync
,改用v-model参数实现双向绑定。html<!-- Vue 2 --> <ChildComponent :title.sync="pageTitle" /> <!-- Vue 3 --> <ChildComponent v-model:title="pageTitle" />
合并行为:当同时使用普通属性和v-bind绑定时,后者会覆盖前者。
html<div id="static" :id="dynamicId"></div> <!-- 渲染结果:<div id="dynamic"></div> -->
v-on
v-on:表达式
,用于监听 DOM 事件或自定义事件,并执行对应的 JavaScript 代码或方法。
语法:
html<!-- 监听事件并执行表达式 --> <div v-on:事件名="表达式"></div> <!-- 简写形式(推荐) --> <div @事件名="表达式"></div>
示例:
html<button @click="count += 1">点击增加</button> <button @mouseover="showTooltip = true">悬停提示</button>
特性:
绑定方法:将事件直接绑定到组件中定义的方法。
html<button @click="handleClick">提交</button>
jsmethods: { handleClick() { console.log("按钮被点击"); } }
传递参数:
手动传递参数
html<button @click="handleDelete(item.id)">删除</button>
jsmethods: { handleDelete(id) { this.items = this.items.filter(item => item.id !== id); } }
获取原生事件对象
$event
:当需要同时传递参数和原生事件对象时,显式传递$event
。html<button @click="handleSubmit('参数', $event)">提交</button>
jsmethods: { handleSubmit(arg, event) { event.preventDefault(); console.log("参数:", arg); } }
事件修饰符:Vue 提供了事件修饰符,用于简化常见的事件处理逻辑。
.stop
:阻止事件冒泡,等价于event.stopPropagation()
。.prevent
:阻止默认行为,等价于event.preventDefault()
。.capture
:使用事件捕获模式,从外到内触发。.self
:仅当事件从元素本身触发时(非子元素)才执行回调。.once
:事件只触发一次,Vue3 中也可用于组件事件。.passive
:表示不阻止默认行为。提升滚动性能,与 addEventListener 的 passive 选项一致。慎用,不可与.prevent
同时使用。.native
:监听原生事件(Vue3已废弃)。
html<!-- 阻止表单默认提交和事件冒泡 --> <form @submit.prevent.stop="onSubmit"></form> <!-- 点击事件最多触发一次 --> <button @click.once="handleOnce">仅一次</button> <!-- 滚动事件使用 passive 修饰符优化性能 --> <div @scroll.passive="onScroll"></div>
按键修饰符:用于监听特定键盘按键的事件,如 Enter、Esc 等。
常用按键别名:
html<input @keyup.enter="submit" /> <!-- 回车键 --> <input @keyup.esc="closeModal" /> <!-- Esc 键 --> <input @keyup.space="playPause" /> <!-- 空格键 --> <input @keyup.delete="clearInput" /> <!-- 删除键 -->
自定义按键码:按键码
keyCode
,Vue 2 支持,Vue 3 已废弃。html<input @keyup.13="submit" /> <!-- Vue2 中支持 -->
组合键修饰符
html<input @keyup.ctrl.enter="save" /> <!-- Ctrl + Enter --> <input @keyup.alt.s="save" /> <!-- Alt + S -->
动态事件名:通过动态属性名绑定不同事件。
html<button @[eventName]="handleEvent"></button>
jsdata() { return { eventName: "click" }; }
在组件上监听自定义事件:用于父子组件通信,通过
$emit
触发。html<!-- 父组件监听子组件的自定义事件 --> <ChildComponent @custom-event="handleCustomEvent" />
js// 子组件触发事件 this.$emit("custom-event", arg1, arg2);
避免内联复杂表达式:推荐将逻辑封装到方法中,而非直接在模板中编写复杂表达式。
html<!-- 不推荐 --> <button @click="count += 1; logCount()">增加</button> <!-- 推荐 --> <button @click="handleIncrement">增加</button>
v-model@
v-model:表达式
,用于在表单输入元素或自定义组件上实现双向数据绑定,是 v-bind 和 v-on 的语法糖。
语法:
html<!-- 基础用法 --> <input v-model="dataProperty" /> <!-- 等价于手动绑定 --> <input :value="dataProperty" @input="dataProperty = $event.target.value" />
特性:
响应式:表单输入的值与 Vue 实例中的
dataProperty
保持同步。不同类型表单元素的使用:
文本输入:input[type=text]和textarea
html<input type="text" v-model="message" /> <textarea v-model="content"></textarea>
复选框:
单个复选框:绑定布尔值。
html<input type="checkbox" v-model="isAgreed" /> 同意协议
多个复选框:绑定数组。
html<input type="checkbox" value="vue" v-model="skills" /> Vue <input type="checkbox" value="react" v-model="skills" /> React
jsdata() { return { skills: [] }; }
单选按钮:
html<input type="radio" value="male" v-model="gender" /> 男 <input type="radio" value="female" v-model="gender" /> 女
jsdata() { return { gender: "" }; }
下拉选择:
单选:
html<select v-model="selectedCity"> <option value="bj">北京</option> <option value="sh">上海</option> </select>
多选:
html<select v-model="selectedTags" multiple> <option value="tag1">标签1</option> <option value="tag2">标签2</option> </select>
修饰符:
.lazy
:将 input 事件改为 change 事件,输入完成后才同步数据。.number
:自动将输入值转为数字类型,避免字符串转换问题。.trim
:自动去除输入值首尾空格。
html<!-- 输入完成后同步 --> <input v-model.lazy="message" /> <!-- 强制转为数字 --> <input type="number" v-model.number="age" /> <!-- 去除首尾空格 --> <input v-model.trim="username" />
在自定义组件中使用:
Vue2 的实现:默认使用
value
属性 和input
事件。html<!-- 父组件 --> <CustomInput v-model="inputValue" /> <!-- 子组件 --> <input :value="value" @input="$emit('input', $event.target.value)" />
js// 子组件声明 props: ["value"],
Vue3 的改进:
默认使用
modelValue
prop 和update:modelValue
事件。html<!-- 父组件 --> <CustomInput v-model="count"/> <!-- 等价于以下写法 --> <CustomInput :modelValue="count" @update:modelValue="count = $event"/>
html<!-- 子组件 --> <template> <button @click="hdlUpdateCount">修改Count</button> </template> <script setup> const props = defineProps({ modelValue: { type: Number, default:0 } }) const emit = defineEmits(['update:modelValue']) function hdlUpdateCount() { emit('update:modelValue', 999) } </script>
支持自定义参数名(多个双向绑定)。
html<!-- 父组件 --> <CustomInput v-model:title="pageTitle" v-model:content="pageContent" /> <!-- 等价于以下写法 --> <CustomInput :title="pageTitle" @update:title="pageTitle = $event" :content="pageContent" @update:content="pageContent = $event" />
html<!-- 子组件 --> <template> <button @click="hdlUpdateTitle">修改Title</button> <button @click="hdlUpdateContent">修改Content</button> </template> <script setup> const props = defineProps({ title: { type: String, default: '' } content: { type: String default: '' } }) const emit = defineEmits(['update:title', 'update:content']) function hdlUpdateTitle() { emit('update:title', '修改后的标题') } function hdlUpdateContent() { emit('update:content', '修改后的内容') } </script>
修改默认行为:通过组件的 model 选项(Vue2)或 v-model 参数(Vue3)自定义.
js// Vue 2 自定义 prop 和事件 model: { prop: "selected", event: "change" }
条件渲染
v-show
v-show:布尔表达式
,用于通过切换 CSS 的 display 属性来控制元素的显示与隐藏。
语法:
html<div v-show="布尔表达式"></div>
示例:
html<div v-show="isVisible">此内容会根据 isVisible 显示/隐藏</div>
jsdata() { return { isVisible: true } }
特性:
实现原理:
- 当表达式为 true 时:移除元素的
display: none
样式。 当表达式为 false 时:添加内联样式display: none
。
- 当表达式为 true 时:移除元素的
对比v-if:
DOM操作:
- v-show:始终保留元素,仅切换 display。
- v-if:条件为假时移除元素。
初始渲染开销:
- v-show:较高,无论条件如何都渲染元素。
- v-if:较低,条件为假时不渲染。
切换开销:
- v-show:较低,仅修改 CSS。
- v-if:较高,触发组件销毁 / 重建。
适用场景:
- v-show:频繁切换显示状态,如选项卡。
- v-if:条件很少变化,如一键展开 / 收起。
不支持
<template>
元素:v-show必须作用在实际渲染的DOM元素上,不可用于<template>
。html<!-- 错误用法 --> <template v-show="condition"> <div>内容</div> </template> <!-- 正确用法 --> <div v-show="condition"> <div>内容</div> </div>
v-if、v-else、v-else-if
v-if、v-else、v-else-if:条件表达式
,用于实现条件渲染,根据表达式的真假动态控制元素的渲染或销毁。元素会从DOM中移除。
语法:
html<div v-if="条件表达式"></div> <div v-else-if="条件表达式"></div> <div v-else></div>
示例:
html<div v-if="score >= 90">优秀</div> <div v-else-if="score >= 80">良好</div> <div v-else-if="score >= 60">及格</div> <div v-else>不及格</div>
特性:
条件链必须连续:指令链必须严格遵循
v-if
→v-else-if
→v-else
的顺序,中间不能插入其他元素。控制组件/元素的销毁与重建:v-if 为 false 时,元素及其子组件会被销毁并移出 DOM。频繁切换性能会有影响。
结合
<template>
:使用<template>
包裹多个元素实现分组条件渲染。html<template v-if="showSection"> <h1>标题</h1> <p>内容</p> </template> <template v-else> <div>替代内容</div> </template>
状态不保留:
v-if 为 false 时,元素内部状态(如表单输入值)会被销毁,重新渲染时重置。
解决方案:使用
<keep-alive>
包裹元素以缓存状态。html<keep-alive> <component v-if="isActive"></component> </keep-alive>
异步组件:若条件依赖异步数据,需确保数据加载完成后再渲染。
html<div v-if="!isLoading && data"> {{ data.content }} </div>
列表渲染
v-for
v-for:表达式
,用于基于数据源(数组、对象、数值范围)循环渲染多个元素或组件。
语法:
html<元素 v-for="(item, index?) in data" :key="唯一标识"> {{ item.attr }} </元素>
item:
any
,当前遍历的元素值,数组项 / 对象属性值 / 数值。index?:
string | number
,当前项的索引或键名。data:
any
,支持数组、对象、数值范围。:key:
any
,用于标识元素唯一性,优化虚拟DOM的更新性能。特性:
遍历不同类型数据源:
遍历数组:
html<ul> <li v-for="(item, index) in items" :key="item.id"> {{ index + 1 }}. {{ item.name }} <!-- 输出:1. Apple--> </li> </ul>
jsdata() { return { items: [ { id: 1, name: "Apple" }, { id: 2, name: "Banana" } ] }; }
遍历对象:
html<ul> <li v-for="(value, key, index) in obj" :key="key"> {{ index }}. {{ key }}: {{ value }} <!-- 输出:0. title: Vue 教程--> </li> </ul>
jsdata() { return { obj: { title: "Vue 教程", author: "John" } }; }
遍历数值范围:
html<span v-for="n in 5" :key="n">{{ n }} </span> <!-- 输出:1 2 3 4 5 -->
:key
:作用:
- 唯一标识:帮助 Vue 识别元素身份,避免重复渲染或状态错乱。
- 性能优化:基于 key 复用已有 DOM 节点,减少不必要的重新渲染。
用法:
唯一性:使用稳定且唯一的标识,如
item.id
,避免用索引index
。html<!-- 错误:用索引作为 key --> <div v-for="(item, index) in list" :key="index"> {{ item.name }} </div>
结合v-if:v-for 的优先级高于 v-if(Vue2)。若需先判断条件再循环,可将 v-if 置于外层元素。
html<!-- 正确写法 --> <template v-if="hasData"> <div v-for="item in list" :key="item.id"> {{ item.name }} </div> </template>
结合计算属性:推荐使用计算属性过滤数据,而非在模板中直接操作。
html<div v-for="item in filteredList" :key="item.id">{{ item.name }}</div>
jscomputed: { filteredList() { return this.list.filter(item => item.isActive); } }
性能优化:
避免超大列表:对超长列表(如1000+项)使用虚拟滚动技术,如 vue-virtual-scroller。
减少响应式依赖:对不需要响应式的静态数据,使用
Object.freeze
冻结。jsdata() { return { list: Object.freeze([...]) // 禁止 Vue 追踪其变化 }; }
扁平化数据结构:避免嵌套过深的响应式对象,优先使用扁平化数据。
在组件中使用:
传递 Props:在组件上使用 v-for 时,需显式传递数据。
html<ChildComponent v-for="item in list" :key="item.id" :item="item" @custom-event="handleEvent" />
组件状态保留:若组件需要保留内部状态(如输入框内容),需确保
:key
唯一且稳定。html<UserInput v-for="user in users" :key="user.id" :user="user" />
key@
key:唯一标识
,用于标识虚拟 DOM 节点身份的特殊属性,它在 Vue 的响应式更新机制中起到优化渲染性能和维护组件状态的关键作用。
语法:
html<元素 :key="唯一标识符"></元素> <!-- 在元素上绑定 key --> <组件 :key="唯一标识符"></组件> <!-- 在组件上绑定 key -->
唯一标识:
- 唯一性:同一父级下,每个 key 必须唯一,不可重复。
- 稳定性:key 值应在数据变化时保持稳定,如id而非index。
特性:
核心作用:
- 优化虚拟DOM对比(Diff 算法):Vue 通过 key 识别节点身份,减少不必要的 DOM 操作。
- 相同 key:复用现有节点,仅更新变化部分。
- 不同 key:销毁旧节点,创建新节点。
- 维护组件/元素状态:当元素或组件因为如列表重新排序而数据变化被复用时,key 可确保其内部状态如输入框内容、滚动位置不被意外保留。
- 优化虚拟DOM对比(Diff 算法):Vue 通过 key 识别节点身份,减少不必要的 DOM 操作。
应用场景:
v-for列表渲染:在 v-for 循环中,每个元素必须绑定唯一 key。
强制替换元素/组件:当需要完全替换元素或组件而非复用,如切换表单类型,可通过改变key强制重新渲染。
html<!-- 切换登录方式时,清空输入框 --> <div v-if="isEmailLogin"> <input key="email" placeholder="邮箱"> </div> <div v-else> <input key="phone" placeholder="手机号"> </div>
动态组件强制刷新:为
<component>
绑定key,避免组件复用导致的生命周期钩子未触发。html<component :is="currentComponent" :key="currentComponent"></component>
过渡动画强制刷新:确保过渡动画在元素身份变化时正确触发。
html<transition> <div :key="state">{{ state }}</div> </transition>
底层原理:
- 虚拟DOM Diff过程:
- 无key:Vue 采用 “就地更新” 策略,按索引顺序对比节点,可能导致错误复用。
- 有key:通过 key 精准匹配相同节点,最小化 DOM 操作。
- 状态保留机制:
- 相同key:复用元素,保留表单值、滚动位置等状态。
- 不同key:销毁旧元素,初始化新元素。
- 虚拟DOM Diff过程:
其他
v-once
v-once:空
,用于标记元素或组件仅渲染一次,后续数据变化时不再更新。
语法:
html<元素 v-once>{{ 静态内容 }}</元素> <!-- 元素上使用 --> <组件 v-once></组件> <!-- 组件上使用 -->
示例:
html// 首次渲染后冻结组件 <template> <UserProfile v-once :initialData="userData" /> <!-- 用户资料不再更新 --> </template>
特性:
核心作用:
- 单次渲染:初始渲染后,元素/组件及其子内容不再响应数据变化。
- 性能优化:减少不必要的虚拟 DOM 比对,提升渲染效率。
使用场景:
静态内容优化:
html<!-- 标题永不更新 --> <h1 v-once>{{ initialTitle }}</h1>
复杂计算的缓存:
html<!-- 计算密集型数据只计算一次 --> <div v-once>{{ heavyCompute(data) }}</div>
避免子组件更新:
html<!-- 父组件数据变化时,子组件不更新 --> <ChildComponent v-once :prop="staticData" />
作用范围:影响整个元素及其子树,包括子组件。若子组件依赖动态 props,v-once 会阻止其更新。
v-cloak
v-cloak:空
,用于在 Vue 实例完成编译前隐藏未编译的模板内容,避免页面加载时出现原始模板符号({ { } }
)的短暂闪烁。必需配合 CSS 样式,CSS 必须全局生效。
语法:
html<!-- 在根元素或需要隐藏的元素上添加 v-cloak --> <div v-cloak>{{ message }}</div>
css/** CSS 必须全局生效 */ [v-cloak] { display: none !important; }
示例:
html<!DOCTYPE html> <html> <head> <style> [v-cloak] { display: none; } </style> </head> <body> <div id="app" v-cloak> <p>{{ message }}</p> </div> <script src="https://unpkg.com/vue@3"></script> <script> Vue.createApp({ data() { return { message: "Hello Vue!" }; } }).mount('#app'); </script> </body> </html>
特性:
实现原理:
- 初始阶段:元素带有 v-cloak 属性,CSS 将其隐藏。
- 编译完成:Vue 移除所有 v-cloak 属性,元素显示渲染后的内容。
配合异步加载:若 Vue 实例异步加载,如按需加载,v-cloak 仍可确保内容隐藏直至编译完成。
html<div v-cloak> <p v-if="loaded">{{ data }}</p> </div>