一、什么是模板语法?我们可以把 vue.js 的模板语法,直接理解为 html 语法的一种扩展,它所有的模板节点声明、属性设置和事件注册等都是按照 html 的语法来进行扩展设计的。按照官方的说法就是“所有的 vue 模板都是语法层面合法的 html,可以被符合规范的浏览器和 html 解析器解析”。
vue 使用一种基于 html 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 dom 上
二、内容渲染指令1. v-text使用 v-tex t指令,将数据采用纯文本方式填充其空元素中
// 组合式<script setup> import { reactive } from 'vue' let student = reactive({ name: 'jack', desc: '<h4>我是来自中国的小朋友!</h4>' }) </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: '<h4>我是来自中国的小朋友!</h4>'})</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: '<h4>我是来自中国的小朋友!</h4>'})</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-modelv-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> <!-- 默认情况下,复选框的值:true/false --> <input type="checkbox" v-model="open"> 灯 <hr> <!-- 自定义复选框值: true-value/false-value --> <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的修饰符修饰符作用示例
.number 自动将用户的输入值转为数值类型 <input v-model.number="age" />
.trim 自动过滤用户输入的首尾空白字符 <input v-model.trim="msg" />
.lazy 在 chang 时而非 input 时更新 <input v-model.lazy="msg" />
// 组合式<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://cache.yisu.com/upload/information/20230306/112/35391.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 class="redback" 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> <!-- 直接使用数组数据源,数组中有哪些值,直接在该元素的class里出现对应的类名 --> <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 :>我是一个普通的按钮</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 :>我是一个普通按钮</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 :>我是一个普通按钮</button></template><style>button { padding: 15px 20px; border: none;}</style>
五、条件渲染指令1. v-if、v-else-if、v-elsev-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时会销毁该元素 --> <h4 v-if="isshow">这是一个普通的标题标签</h4> <hr> 年龄: <input type="range" min="0" max="100" v-model="age"> {{ age }} <!-- v-if:可以配合 v-else-if 和 v-else 来搭建多重判断条件,他们中间不要参杂无关紧要的元素 --> <h2 v-if="age < 18">未成年</h2> <!-- <span>无关紧要的元素</span> --> <h3 v-else-if="age < 35">青年</h3> <h4 v-else-if="age < 50">中年</h4> <h5 v-else>老年</h5> <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"> <h2>可以游泳</h2> </template> <template v-else> <h2>不可以游泳</h2> </template></template>
2. v-showv-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 样式 --> <h4 v-show="isshow">这是一个普通的标题标签</h4> <hr> 年龄: <input type="range" min="0" max="100" v-model="age"> {{ age }} <h2 v-show="age < 18">未成年</h2> <h3 v-show="age >= 18 && age < 35">青年</h3> <h4 v-show="age >= 35 && age < 50">中年</h4> <h5 v-show="age >= 50">老年</h5> <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"> <h2>可以游泳</h2> </template> <template v-shw="week == 12 || week == 4 || week == 6"> <h2>不可以游泳</h2> </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> <h4>当前音量:{{ volume }}</h4> <!-- 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 阻止默认行为
.stop 阻止事件冒泡
.capture 以捕获模式触发当前的事件处理函数
.once 绑定的事件只触发1次
.self 只有在event.target是当前元素自身时触发事件处理函数
.passive 向浏览器表明了不想阻止事件的默认行为
.prevent.prevent :阻止该事件的默认行为
// 组合式<script setup>// 打招呼function say(name) { window.alert('你好:' + name)}</script><template> <!-- .prevent 修饰符阻止了超链接的默认行为(跳转到百度页) --> <a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" @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" rel="external nofollow" rel="external nofollow" @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:循环的数组 --> <h7>v-for 渲染数组, v-for="item in itmes"</h7> <ul> <li v-for="sub in subject"> 编号:{{ sub.id }} --- 名称:{{ sub.name }} </li> </ul> <hr> <!-- 解构对象 --> <h7>v-for 渲染数组, v-for="{ 解构…… } in itmes"</h7> <ul> <li v-for="{ id , name } in subject"> 编号:{{ id }} --- 名称:{{ name }} </li> </ul> <hr> <!-- (value, index) in itmes value:值 index:索引 itmes:循环的数组 --> <h7>v-for 渲染数组, v-for="(value, index) in itmes"</h7> <ul> <li v-for="(sub, index) in subject"> 编号:{{ sub.id }} --- 名称:{{ sub.name }} --- 索引:{{ index }} </li> </ul> <hr> <!-- 解构对象 --> <h7>v-for 渲染数组, v-for="({ 解构…… }, index) in itmes"</h7> <ul> <li v-for="({ id , name } , index) in subject"> 编号:{{ id }} --- 名称:{{ name }} --- 索引:{{ index }} </li> </ul></template>
2. v-for渲染对象使用 v-for 来遍历一个对象的所有属性,遍历的顺序会基于对该对象调用 object.keys() 的返回值来决定
语法:
in 前一个参数:value in object
value :属性值
items :需要循环的对象in 前两个参数:(value, name) in object
value :属性值
name :键
items :需要循环的对象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:循环的对象 --> <h7>v-for 渲染对象, v-for="value in object"</h7> <ul> <li v-for="value in student"> {{ value }} </li> </ul> <hr> <!-- (value, name) in object value:属性值 name:属性名 object:循环的对象 --> <h7>v-for 渲染对象, v-for="(value, name) in object"</h7> <ul> <li v-for="(value, name) in student"> 属性名:{{ name }} --- 属性值: {{ value }} </li> </ul> <hr> <!-- (value, name, index) in object value:属性值 name:属性名 index: 索引 object:循环的对象 --> <h7>v-for 渲染对象, v-for="(value, name, index) in object"</h7> <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> <h4>不使用key值</h4> <ul> <li v-for="sub in subject"> <input type="checkbox"> {{ sub }} </li> </ul> <hr> <h4>使用索引当key值</h4> <ul> <li v-for="(sub, index) in subject" :key="index"> <input type="checkbox"> {{ sub }} </li> </ul> <hr> <h4>使用列表属性当key值(该属性必须再此列表中唯一)</h4> <ul> <li v-for="sub in subject" :key="sub.id"> <input type="checkbox"> {{ sub }} </li> </ul></template>
以上就是如何使用vue3的模板语法?的详细内容。