
“这里是云端源想IT,帮你轻松学IT”
嗨~ 今天的你过得还好吗?
愿你付出甘之如饴
所得归于欢喜
– 2023.07.13 –
上期带大家认识了Vue 3 前端框架,并且了解了Vue 3值得关注的新特性。Vue.js 从版本 1.x 到版本 3.x,官方代码案例和推荐使用都是模板语法,那么本篇文章我们也根据官方的推荐,来了解一下模板语法是怎么一回事。

一、什么是模板语法
我们可以把 Vue.js 的模板语法,直接理解为 HTML 语法的一种扩展,它所有的模板节点声明、属性设置和事件注册等都是按照 HTML 的语法来进行扩展设计的。按照官方的说法就是“所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析”。

在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。
二、内容渲染指令
1、 v-text
使用 v-tex t指令,将数据采用纯文本方式填充其空元素中。
// 组合式
<script setup>
import { reactive } from 'vue'
let student = reactive({
name: 'Jack',
desc: '<h3>我是来自中国的小朋友!</h3>'
})
</script>
<template>
<!-- 使用v-text指令,将数据采用纯文本方式填充其空元素中 -->
<div v-text="student.name"></div>
<!-- v-text:以纯文本的方式显示数据 -->
<div v-text="student.desc"></div>
<!-- 下面的代码会报错:div 元素不是空元素 -->
<!-- <div v-text="student.name">这是原始的div数据</div> -->
</template>
2、 {{ }} 插值表达式
在元素中的某一位置采用纯文本的方式渲染数据。
// 组合式
<script setup>
import { reactive } from 'vue'
let student = reactive({
name: 'Jack',
desc: '<h3>我是来自中国的小朋友!</h3>'
})
</script>
<template>
<!-- 插值表达式:在元素中的某一位置采用纯文本的方式渲染数据 -->
<div>这是一个 DIV 元素,{{ student.name }},{{ student.desc }}</div>
</template>
3、 v-html
使用 v-html 指令,将数据采用 HTML 语法填充其空元素中。
// 组合式
<script setup>
import { reactive } from 'vue'
let student = reactive({
name: 'Jack',
desc: '<h3>我是来自中国的小朋友!</h3>'
})
</script>
<template>
<!-- 使用v-html指令,将数据采用HTML语法填充其空元素中 -->
<div v-html="student.name"></div>
<!-- v-html:以 HTML 语法显示数据 -->
<div v-html="student.desc"></div>
<!-- 下面的代码会报错:div 元素不是空元素 -->
<!-- <div v-html="student.name">这是原始的div数据</div> -->
</template>
三、双向绑定指令
1、 v-model
v-model 双向数据绑定指令,视图数据和数据源同步。
一般情况下 v-model 指令用在表单元素中:
- 文本类型的 <input> 和 <textarea> 元素会绑定 value 属性并侦听 input 事件;
- <input type=”checkbox”> 和 <input type=”radio”> 会绑定 checked 属性并侦听 change 事件;
- <select>会绑定 value 属性并侦听 change 事件。
// 组合式
<script setup>
import { ref } from 'vue'
let inputText = ref('ABC') // 单行文本框
let message = ref('本次更新有以下几点:……') // 多行文本框
let open = ref(true) // 开灯(复选框)
let determine = ref('不确定') // 是否确定(复选框)
let likes = ref(['YMQ']) // 兴趣爱好(复选框)
let sex = ref('woman') // 性别(单选按钮)
let level = ref('B') // // 证书等级(单选下拉框)
let city = ref(['苏C', '苏B']) // 去过的城市(多选下拉框)
</script>
<template>
<input type="text" v-model="inputText">
<hr>
<textarea v-model="message"></textarea>
<hr>
<input type="checkbox" v-model="open"> 灯
<hr>
<input type="checkbox" true-value="确定" false-value="不确定" v-model="determine"> 是否确定
<hr>
<input type="checkbox" value="LQ" v-model="likes"> 篮球
<input type="checkbox" value="ZQ" v-model="likes"> 足球
<input type="checkbox" value="YMQ" v-model="likes"> 羽毛球
<input type="checkbox" value="PPQ" v-model="likes"> 乒乓球
<hr>
<input type="radio" value="man" v-model="sex"> 男
<input type="radio" value="woman" v-model="sex"> 女
<hr>
证书等级:
<select v-model="level">
<option value="C">初级</option>
<option value="B">中级</option>
<option value="A">高级</option>
</select>
<hr>
去过的城市:
<select multiple v-model="city">
<option value="苏A">南京</option>
<option value="苏B">无锡</option>
<option value="苏C">徐州</option>
<option value="苏D">常州</option>
</select>
</template>

2、 v-model的修饰符
// 组合式
<script setup>
import { ref } from 'vue'
let age = ref(20)
let nickname = ref('')
</script>
<template>
<p>将用户输入的值转成数值 .number,懒更新 .lazy</p>
<!-- 。number 将用户输入的值转成数值,如果用户输入的内容无法转成数字,将不会更新数据源 -->
<!-- .lazy 在 change 跟新数据源,而不是 input -->
<input type="text" v-model.lazy.number="age">
<hr>
<p>去掉首尾空白字符</p>
<input type="text" v-model.trim="nickname">
</template>
四、属性绑定指令
响应式地绑定一个元素属性,应该使用 v-bind:指令。如果绑定的值是 null 或者 undefined,那么该属性将会从渲染的元素上移除。由于 v-bind 超级常用,我们提供了特定的简写语法:
// 组合式
<script setup>
import { reactive } from 'vue'
let picture = reactive({
src: 'https://uploadfile.bizhizu.cn/2015/0424/20150424015229741.jpg', // 图像地址
width: 200 // 显示宽度
})
</script>
<template>
<input type="range" min="100" max="500" v-model="picture.width">
<hr>
<!-- v-bind: 为 src 属性绑定指定的数据源 -->
<img v-bind:src="picture.src" v-bind:width="picture.width">
<hr>
<!-- : 是 v-bind: 的缩写形式 -->
<img :src="picture.src" :width="picture.width">
<hr>
<!-- 如果绑定的值是 null 或者 undefined,那么该属性将会从渲染的元素上移除 -->
<button @click="picture.width = null">设置宽度为NULL</button>
</template>

1、动态绑定多个属性值
直接使用 v-bind 来为元素绑定多个属性及其值。
// 组合式
<script setup>
import {reactive} from 'vue'
let attrs = reactive({
class: 'error',
id: 'borderBlue'
})
</script>
<template>
<!-- 直接使用 v-bind 来为元素绑定多个属性及其值 -->
<button v-bind="attrs">我是一个普通的按钮</button>
</template>
<style>
.error {
background-color: rgb(167, 58, 58);
color: white;
}
#borderBlue {
border: 2px solid rgb(44, 67, 167);
}
</style>
渲染结果:
<button id="btnBorderBlue">我是一个普通按钮</button>
2、 绑定class和style属性
class 和 style 可以和其他属性一样使用 v-bind 将它们和动态的字符串绑定;但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。
因此, Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强;除了字符串外,表达式的值也可以是对象或数组。
class属性绑定
绑定对象
// 组合式
<script setup>
import { ref, reactive } from 'vue'
let btnClassObject = reactive({
error: false, // 主题色
flat: false // 阴影
})
let capsule = ref(false)// 胶囊
let block = ref(false)// 块
</script>
<template>
<input type="checkbox" v-model="btnClassObject.error"> error
<input type="checkbox" v-model="btnClassObject.flat"> flat
<br>
<br>
<button :class="btnClassObject">我是一个普通的按钮</button>
<hr>
<input type="checkbox" v-model="capsule"> 胶囊
<input type="checkbox" v-model="block"> 块
<br>
<br>
<button :class="{ 'rounded': capsule, 'fullWidth': block }">我是一个普通的按钮</button>
</template>
<style>
button {
border: none;
padding: 15px 20px;
background-color: rgb(179, 175, 175);
}
.error {
background-color: rgb(167, 58, 58);
color: white;
}
.flat {
box-shadow: 0 0 8px gray;
}
.rounded {
border-radius: 100px;
}
.fullWidth {
width: 100%;
}
</style>

绑定数组
// 组合式
<script setup>
import { ref, reactive } from 'vue'
let btnTheme = ref([]) // 按钮class数组
let capsule = ref(false)// 胶囊
let widthTheme = ref([])// 宽度数组
</script>
<template>
<input type="checkbox" value="error" v-model="btnTheme"> error
<input type="checkbox" value="flat" v-model="btnTheme"> flat
<br>
<br>
<button :class="btnTheme">我是一个普通的按钮</button>
<hr>
<input type="checkbox" v-model="capsule"> 胶囊
<input type="checkbox" value="fullWidth" v-model="widthTheme"> 块
<br>
<br>
<button :class="[{ 'rounded': capsule }, widthTheme]">我是一个普通的按钮</button>
</template>
<style>
button {
border: none;
padding: 15px 20px;
background-color: rgb(179, 175, 175);
}
.error {
background-color: rgb(167, 58, 58);
color: white;
}
.flat {
box-shadow: 0 0 8px gray;
}
.rounded {
border-radius: 100px;
}
.fullWidth {
width: 100%;
}
</style>

style属性绑定
绑定对象
// 组合式
<script setup>
import { reactive, ref } from 'vue'
let btnTheme = reactive({
backgroundColor: '#FF0000', // 背景色
color: '#000000' // 文本色
})
let backColor = ref('#0000FF') // 背景色
let color = ref('#FFFFFF') // 文本色
let borRadius = ref(20) // 边框圆角
</script>
<template>
背景色:<input type="color" v-model="btnTheme.backgroundColor">
文本色:<input type="color" v-model="btnTheme.color">
<br>
<br>
<!-- style:可以直接绑定对象数据源,但是对象数据源的属性名当样式属性(驼峰命名法,kebab-cased形式) -->
<button :style="btnTheme">我是一个普通的按钮</button>
<hr>
背景色:<input type="color" v-model="backColor">
文本色:<input type="color" v-model="color">
边框圆角:<input type="range" min="0" max="20" v-model="borRadius">
<br>
<br>
<!-- style:可以直接写对象,但是对象的属性名当样式属性(驼峰命名法,kebab-cased形式) -->
<button :style="{
backgroundColor: backColor,
color,
'border-radius': borRadius + 'px'
}">我是一个普通的按钮</button>
</template>
<style>
button {
border: none;
padding: 15px 20px;
background-color: rgb(179, 175, 175);
}
</style>
绑定数组
还可以给 :style 绑定一个包含多个样式对象的数组,这些对象会被合并后渲染到同一元素上。
// 组合式
<!-- 脚本区域 -->
<script setup>
import { ref, reactive } from 'vue'
const btnTheme = ref([
{
backgroundColor: '#FF0000', // 背景色
color: '#FFFFFF' // 文本色
},
{
borderRadius: 0 // 边框圆角
}
])
const colorTheme = reactive({
backgroundColor: '#000000', // 背景色
color: '#FFFFFF' // 文本色
})
const radiusTheme = reactive({
borderRadius: 0 // 边框圆角
})
</script>
<!-- 视图区域 -->
<template>
背景色:<input type="color" v-model="btnTheme[0].backgroundColor">
文本色:<input type="color" v-model="btnTheme[0].color">
胶囊:<input type="checkbox" true-value="5px" false-value="0" v-model="btnTheme[1].borderRadius">
<br>
<br>
<!-- 直接传入数组 -->
<button :style="btnTheme">我是一个普通按钮</button>
<hr>
背景色:<input type="color" v-model="colorTheme.backgroundColor">
文本色:<input type="color" v-model="colorTheme.color">
胶囊:<input type="checkbox" true-value="5px" false-value="0" v-model="radiusTheme.borderRadius">
<br>
<br>
<!-- 直接写数组 -->
<button :style="[colorTheme, radiusTheme]">我是一个普通按钮</button>
</template>
<style>
button {
padding: 15px 20px;
border: none;
}
</style>
五、条件渲染指令
1. v-if、v-else-if、v-else
- v-if 指令用于条件性地渲染元素;该内容只会在指令的表达式返回真值时才被渲染;
- v-else-if 提供的是相应于 v-if 的 else if 区块,它可以连续多次重复使用;
- 你也可以使用 v-else 为 v-if 添加一个 else 区块;
- v-else 和 v-else-if 指令必须配合 v-if 指令一起使用 ,否则它将不会被识别,而且语句块中间不能出现无关其他元素;
- v-if 支持在 <template> 元素上使用,这只是一个不可见的包装器元素,最后渲染的结果并不会包含这个 <template> 元素。
// 组合式
<script setup>
import { ref } from 'vue'
let isShow = ref(false) // 是否显示
let age = ref(20) // 年龄
let week = ref(3) // 周几
</script>
<template>
是否显示:<input type="checkbox" v-model="isShow">
<!--
v-if:指令表达式为真时才会渲染该元素
为true时会创建该元素,为false时会销毁该元素
-->
<h3 v-if="isShow">这是一个普通的标题标签</h3>
<hr>
年龄: <input type="range" min="0" max="100" v-model="age"> {{ age }}
<!--
v-if:可以配合 v-else-if 和 v-else 来搭建多重判断条件,他们中间不要参杂无关紧要的元素
-->
<h1 v-if="age < 18">未成年</h1>
<!-- <span>无关紧要的元素</span> -->
<h2 v-else-if="age < 35">青年</h2>
<h3 v-else-if="age < 50">中年</h3>
<h4 v-else>老年</h4>
<hr>
周几: <input type="range" min="1" max="7" v-model="week"> {{ week }}
<!-- v-if:可以配合 template 元素使用,最后渲染的结果并不会包含这个 <template>元素 -->
<template v-if="week == 1 || week == 3 || week == 5 || week == 7">
<h1>可以游泳</h1>
</template>
<template v-else>
<h1>不可以游泳</h1>
</template>
</template>

2. v-show
- v-show 按条件显示一个元素的指令;
- v-show 会在 DOM 渲染中保留该元素;
- v-show 仅切换了该元素上名为 display 的 CSS 属性;
- v-show 不支持在 <template> 元素上使用,也不能和 v-else 搭配使用。
// 组合式
<script setup>
import { ref } from 'vue'
let isShow = ref(false) // 是否显示
let age = ref(20) // 年龄
let week = ref(3) // 周几
</script>
<template>
是否显示:<input type="checkbox" v-model="isShow">
<!--
v-show:指令表达式为真时才会渲染该元素
无论该指令的表达式是否 true 或 false,该元素在元素中是保留该元素的
为 true 时会删除该元素的 display:none 样式,为 false 时会给该元素添加 display:none 样式
-->
<h3 v-show="isShow">这是一个普通的标题标签</h3>
<hr>
年龄: <input type="range" min="0" max="100" v-model="age"> {{ age }}
<h1 v-show="age < 18">未成年</h1>
<h2 v-show="age >= 18 && age < 35">青年</h2>
<h3 v-show="age >= 35 && age < 50">中年</h3>
<h4 v-show="age >= 50">老年</h4>
<hr>
周几: <input type="range" min="1" max="7" v-model="week"> {{ week }}
<!-- v-show:不可以配合 template 元素使用 -->
<!-- <template v-show="week == 1 || week == 3 || week == 5 || week == 7">
<h1>可以游泳</h1>
</template>
<template v-shw="week == 12 || week == 4 || week == 6">
<h1>不可以游泳</h1>
</template> -->
</template>

3. v-if和v-show的区别
- v-if 是“真实的”按条件渲染,由于它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。
- v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事;条件区块只有当条件首次变为 true 时才被渲染。
- v-show 元素无论初始条件如何,始终会被渲染,只有 CSS display 属性会被切换。
- v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销;如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。
六、事件绑定指令
我们可以使用 v-on: 指令 (简写为@) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript,用法:v-on:click=”” 或 @click=””。
// 组合式
<script>
export default {
data: () => ({
volume: 5 // 音量[0, 10]
}),
methods: {
// 添大音量
addVolume() {
// 如果音量没有在最高值,则添加音量
if (this.volume !== 10) {
this.volume++
}
},
// 减小音量
subVolume() {
// 如果音量没有在最小值,则减小音量
if (this.volume !== 0) {
this.volume--
}
},
// 设置音量
setVolume(value) {
// 判断音量是否在取值范围之间
if (value >= 0 && value <= 10) {
this.volume = value
}
}
}
}
</script>
<template>
<h3>当前音量:{{ volume }}</h3>
<!-- v-on: 事件绑定 -->
<button v-on:click="addVolume">添加音量</button>
<button v-on:click="subVolume">减小音量</button>
<hr>
<!-- @ 是 v-on: 的缩写 -->
<button @click="setVolume(0)">静音</button>
<button @click="setVolume(5)">音量适中</button>
<button @click="setVolume(10)">音量最大</button>
</template>

1、事件修饰符

.prevent
.prevent :阻止该事件的默认行为。
// 组合式
<script setup>
// 打招呼
function say(name) {
window.alert('你好:' + name)
}
</script>
<template>
<!-- .prevent 修饰符阻止了超链接的默认行为(跳转到百度页) -->
<a href="http://www.baidu.com" @click.prevent="say('baiDu')">百度</a>
</template>
.stop
.stop :阻止事件产生的冒泡现象。
// 组合式
<script setup>
// 打招呼
function say(name) {
console.log('你好:' + name)
}
</script>
<template>
<div class="divArea" @click="say('DIV')">
<!-- .stop:阻止产生冒泡事件 -->
<button @click.stop="say('BUTTON')">冒泡按钮</button>
</div>
</template>
<style>
.divArea {
padding: 30px;
border: 2px solid blue;
}
</style>
.once
.once :绑定的事件只触发 1 次。
// 组合式
<script setup>
// 打招呼
function say(name) {
window.alert('你好:' + name)
}
</script>
<template>
<!-- .once:绑定的事件只触发一次 -->
<button @click.once="say('BUTTON')">点我试一下</button>
</template>

.self
.self :只有在 event.target 是当前元素自身时触发事件处理函数。
// 组合式
<script setup>
// 打招呼
function say(name) {
window.alert('你好:' + name)
}
</script>
<template>
<!-- .self:只在该元素上触发事件有效,其子元素无效 -->
<div class="divArea" @click.self="say('DIV')">
<button>我是一普通的按钮</button>
</div>
</template>
<style>
.divArea {
padding: 30px;
border: 2px solid blue;
}
</style>
capture
.capture :给元素添加一个监听器。
- 当元素事件产生冒泡时,先触发的是该修饰符的元素的事件;
- 如果有多个该修饰符,则由外向内依次触发。
// 组合式
<script setup>
// 打招呼
function say(name) {
console.log('你好:' + name)
}
</script>
<template>
<!--
.capture 给元素添加一个监听器
1:当元素事件产生冒泡时,先触发的是该修饰符的元素的事件
2:如果有多个该修饰符,则由外向内依次触发
-->
<div class="divArea" @click.capture="say('DIV-1')">
<div class="divArea" @click="say('DIV-2')">
<div class="divArea" @click.capture="say('DIV-3')">
<button>我是一普通的按钮</button>
</div>
</div>
</div>
</template>
<style>
.divArea {
padding: 30px;
border: 2px solid blue;
}
</style>
.passive
.passive :不阻止事件的默认行为,与 .prevent 不要同时使用。
// 组合式
<script setup>
function eventPrevent() {
// 阻止事件默认行为
event.preventDefault()
}
</script>
<template>
<!-- .passive:先执行默认行为,不思考执行的代码中是否包含 event.preventDefault() -->
<a href="http://www.baidu.com" @click.passive="eventPrevent">百度</a>
</template>

2、按键修饰符
按键别名:.enter、.tab、.esc、.space、.up、.down、.left、.right、.delete (捕获 Delete 和 Backspace 两个按键)。
系统修饰符:.ctrl、.alt、.shift、.meta。
准确的修饰符:.exact。
// 组合式
<script setup>
// 弹出消息
function showMessage(message) {
window.alert(message)
}
</script>
<template>
按下的键中包含 Enter 键事件: <input type="text" @keydown.enter="showMessage('你按下了 Enter 键')">
<hr>
按下的键中包含 Shift Enter 键事件:<input type="text" @keydown.enter.shift="showMessage('你按下了 Shift + Enter 键')"/>
<hr>
按下的键只有 Shift Enter 键事件:<input type="text" @keydown.enter.shift.exact="showMessage('你只按下了 Shift + Enter 键')"/>
</template>

3、鼠标按键修饰符
鼠标按键修饰符:.left、.right、.middle。
// 组合式
<!-- 脚本区域 -->
<script setup>
function showTest(text) {
window.alert(text)
}
</script>
<!-- 视图区域 -->
<template>
<!-- 鼠标右键按下 -->
<button @mousedown.right="showTest('按下的是鼠标右键')">鼠标右键按下</button>
<hr>
<!-- 点击时,采用的是鼠标中键 -->
<button @click.middle="showTest('按下的是鼠标中键')">点击时,采用的是鼠标中键</button>
<hr>
<!-- 鼠标左键按下 -->
<button @mousedown.left="showTest('按下的是鼠标左键')">鼠标左键按下</button>
</template>
<!-- 样式区域 -->
<style>
button {
border: none;
padding: 15px 20px;
}
button:active {
box-shadow: 0 0 5px grey;
}
</style>
七、列表渲染指令
使用 v-for 指令基于一个数组来渲染一个列表。
1、v-for渲染数组
语法:
- in 前一个参数:item in items
- item :值
- items :需要循环的数组

- in 前两个参数:(value, index) in items
- value :值
- index :索引
- items :需要循环的数组
// 组合式
<script setup>
import { ref } from 'vue'
// 课程
let subject = ref([
{ id: 1, name: 'Vue' },
{ id: 2, name: 'Java' },
{ id: 3, name: 'UI设计' },
{ id: 4, name: 'Hadoop' },
{ id: 5, name: '影视后期' },
])
</script>
<template>
<!--
item in itmes
item:值,当前循环的数组值
itmes:循环的数组
-->
<h6>v-for 渲染数组, v-for="item in itmes"</h6>
<ul>
<li v-for="sub in subject">
编号:{{ sub.id }} --- 名称:{{ sub.name }}
</li>
</ul>
<hr>
<!-- 解构对象 -->
<h6>v-for 渲染数组, v-for="{ 解构…… } in itmes"</h6>
<ul>
<li v-for="{ id , name } in subject">
编号:{{ id }} --- 名称:{{ name }}
</li>
</ul>
<hr>
<!--
(value, index) in itmes
value:值
index:索引
itmes:循环的数组
-->
<h6>v-for 渲染数组, v-for="(value, index) in itmes"</h6>
<ul>
<li v-for="(sub, index) in subject">
编号:{{ sub.id }} --- 名称:{{ sub.name }} --- 索引:{{ index }}
</li>
</ul>
<hr>
<!-- 解构对象 -->
<h6>v-for 渲染数组, v-for="({ 解构…… }, index) in itmes"</h6>
<ul>
<li v-for="({ id , name } , index) in subject">
编号:{{ id }} --- 名称:{{ name }} --- 索引:{{ index }}
</li>
</ul>
</template>

2、v-for渲染对象
使用 v-for 来遍历一个对象的所有属性,遍历的顺序会基于对该对象调用 Object.keys() 的返回值来决定。
语法:
1)in 前一个参数:value in object
- value :属性值
- items :需要循环的对象
2)in 前两个参数:(value, name) in object
- value :属性值
- name :键
- items :需要循环的对象
3)in 前三个参数:(value, name, index) in object
- value :属性值
- name :键
- index :索引
- items :需要循环的对象
// 组合式
<script setup>
import { reactive } from 'vue'
let student = reactive({
styNum: '007', // 学号
name: 'Jack', // 名字
age: 18 //年龄
})
</script>
<template>
<!--
value in object
value:属性值
object:循环的对象
-->
<h6>v-for 渲染对象, v-for="value in object"</h6>
<ul>
<li v-for="value in student">
{{ value }}
</li>
</ul>
<hr>
<!--
(value, name) in object
value:属性值
name:属性名
object:循环的对象
-->
<h6>v-for 渲染对象, v-for="(value, name) in object"</h6>
<ul>
<li v-for="(value, name) in student">
属性名:{{ name }} --- 属性值: {{ value }}
</li>
</ul>
<hr>
<!--
(value, name, index) in object
value:属性值
name:属性名
index: 索引
object:循环的对象
-->
<h6>v-for 渲染对象, v-for="(value, name, index) in object"</h6>
<ul>
<li v-for="(value, name, index) in student">
属性名:{{ name }} --- 属性值: {{ value }} --- 索引:{{ index }}
</li>
</ul>
</template>

3、 通过 key 管理状态
当列表的数据变化时,默认情况下,vue 会尽可能的复用已存在的 DOM 元素,从而提升渲染的性能;但这种默认的性能优化策略,会导致有状态的列表无法被正确更新。
为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能;此时,需要为每项提供一个唯一的key属性。
key 的注意事项:
- key 的类型只能是 Number/String;
- key 值必须具有唯一性;
- 提议循环的列表有一个属性当 key(该属性的值在此列表中唯一);
- 不使用索引当 key;
- 提议使用 v-for 指令时必定要指定 key 的值。
// 组合式
<script setup>
import { ref } from 'vue'
// 课程
let subject = ref([
{ id: 1, name: 'Vue' },
{ id: 2, name: 'Java' },
{ id: 3, name: 'Hadoop' }
])
// 添加课程
function addSubject() {
// (数组最前面)添加
subject.value.unshift({ id: 4, name: 'Python' })
}
</script>
<template>
<button @click.once="addSubject">添加课程(数组最前面)</button>
<h3>不使用key值</h3>
<ul>
<li v-for="sub in subject">
<input type="checkbox">
{{ sub }}
</li>
</ul>
<hr>
<h3>使用索引当key值</h3>
<ul>
<li v-for="(sub, index) in subject" :key="index">
<input type="checkbox">
{{ sub }}
</li>
</ul>
<hr>
<h3>使用列表属性当key值(该属性必须再此列表中唯一)</h3>
<ul>
<li v-for="sub in subject" :key="sub.id">
<input type="checkbox">
{{ sub }}
</li>
</ul>
</template>
以上就是Vue3中的模板语法,文中已经介绍的超级详细了,希望能够协助你更快地掌握Vue3的使用,让你的前端开发更轻松!

我们下期再见!
END
文案编辑|云端学长
文案配图|云端学长
内容由:云端源想分享



