第 1 节 概述
在上一篇文章中,我们用 ref 和 reactive 定义了响应式数据。
现在的问题是:数据怎么显示到页面上?用户的操作怎么触发数据变化?
Vue 3 的模板语法解决的就是这两个问题。我们用一条主线串起来:
1
数据显示 {{ }} → 属性绑定 : → 条件显示 v-if → 列表循环 v-for → 用户点击 @ → 表单输入 v-model
第 2 节 文本插值
双大括号可以把数据插入到模板中:
1
2
3
4
5
6
7
8
9
10
< script setup lang = "ts" >
const name = '张三'
const age = 25
</ script >
< template >
< p > 姓名 : {{ name }}</ p >
< p > 年龄 : {{ age }}</ p >
< p > 表达式 : {{ age + 1 }}</ p >
</ template >
大括号里可以写任意合法的 JavaScript 表达式。
但不要写完整的语句,比如 if 或 for。
第 3 节 属性绑定
3.1 基本用法
用 v-bind 可以把 HTML 属性绑定到变量:
1
2
3
4
5
6
7
8
9
< script setup lang = "ts" >
const id = 'container'
const url = 'https://example.com'
</ script >
< template >
< div v -bind:id = "id" ></ div >
< a v -bind:href = "url" > 链接 </ a >
</ template >
1
2
3
4
< template >
< div :id = "id" ></ div >
< a :href = "url" > 链接 </ a >
</ template >
不加 : 的属性是普通字符串,加了 : 的属性会作为变量或表达式解析。
3.2 class 绑定
:class 可以和普通 class 共存,Vue 会自动合并:
1
2
3
4
5
6
7
8
9
10
11
12
13
< script setup lang = "ts" >
const isActive = ref ( true )
const hasError = ref ( false )
</ script >
< template >
< div
class = "base-style"
: class = "{ active: isActive, error: hasError }"
>
内容
</ div >
</ template >
:class 可以传入对象、数组或组合:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< script setup lang = "ts" >
const classObj = ref ({
active : true ,
'text-white' : false ,
})
const classArr = ref ([ 'px-4' , 'py-2' ])
</ script >
< template >
< div :class = "classObj" ></ div >
< div :class = "classArr" ></ div >
< div : class = "[classObj, classArr]" ></ div >
</ template >
3.3 style 绑定
:style 的用法和 :class 类似:
1
2
3
4
5
6
7
8
9
10
< script setup lang = "ts" >
const styleObj = ref ({
color : 'red' ,
fontSize : '30px' ,
})
</ script >
< template >
< div :style = "styleObj" > 红色大字 </ div >
</ template >
3.4 绑定多个属性
使用无参数的 v-bind 一次传入多个属性:
1
2
3
4
5
6
7
8
9
10
11
< script setup lang = "ts" >
const attr = ref ({
id : 'container' ,
class : 'wrapper' ,
style : 'background-color: green' ,
})
</ script >
< template >
< div v-bind = "attr" ></ div >
</ template >
第 4 节 条件渲染
4.1 v-if 系列
v-if、v-else-if、v-else 根据条件决定是否渲染元素:
1
2
3
4
5
6
7
8
9
< script setup lang = "ts" >
const score = ref ( 85 )
</ script >
< template >
< p v-if = "score >= 90" > 优秀 </ p >
< p v-else-if = "score >= 60" > 及格 </ p >
< p v-else > 不及格 </ p >
</ template >
条件为 false 时,元素根本不会出现在 DOM 中。
4.2 v-show
v-show 也控制显示隐藏,但元素始终存在:
1
2
3
< template >
< p v-show = "isVisible" > 我只是一直隐藏了 </ p >
</ template >
4.3 v-if vs v-show
对比 v-ifv-show渲染方式 条件假时不渲染 始终渲染,用 display: none 隐藏 切换开销 每次切换都创建/销毁 只切换 CSS 初始开销 条件假时无开销 始终有初始渲染开销 适用场景 切换不频繁 频繁切换
技巧
如果条件很少变化,用 v-if。如果条件频繁切换(如标签页),用 v-show。
第 5 节 列表渲染
用 v-for 遍历数组或对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
< script setup lang = "ts" >
const items = ref ([ '苹果' , '香蕉' , '橘子' ])
const user = ref ({
姓名 : '张三' ,
年龄 : 18 ,
性别 : '男' ,
})
</ script >
< template >
< ul >
< li v-for = "(item, index) in items" :key="index" >
{{ index }} : {{ item }}
</ li >
</ ul >
< ul >
< li v-for = "(value, key) in user" :key="key" >
{{ key }} : {{ value }}
</ li >
</ ul >
</ template >
说明
:key 是 Vue 用来追踪每个元素的标识。遍历时建议提供一个唯一值作为 key,能提升渲染性能。
第 6 节 事件处理
6.1 基本用法
用 v-on 监听事件,简写为 @:
1
2
3
4
5
6
7
8
9
10
11
12
< script setup lang = "ts" >
const count = ref ( 0 )
function handleClick () {
count . value ++
}
</ script >
< template >
< p > 点击次数 : {{ count }}</ p >
< button @click ="handleClick" > 点击 </ button >
</ template >
也可以直接写内联表达式:
1
2
3
< template >
< button @click ="count++" > 点击 </ button >
</ template >
6.2 事件修饰符
DOM 事件会经历三个阶段:捕获 → 目标 → 冒泡。
Vue 提供了事件修饰符,简化事件细节的处理:
修饰符 作用 使用场景 .stop阻止事件冒泡 子元素点击不想触发父元素 .prevent阻止默认行为 阻止表单提交、链接跳转 .self只有事件源是自己时才触发 避免子元素误触 .capture在捕获阶段触发 提前拦截事件 .once只触发一次 一次性操作,防止重复提交 .passive不调用 preventDefault 滚动性能优化
修饰符可以串联:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< template >
<!-- 阻止冒泡 -->
< div @click ="parentClick" >
< button @click.stop ="childClick" > 点我 </ button >
</ div >
<!-- 阻止表单刷新 -- >
< form @submit.prevent ="onSubmit" >
< button type = "submit" > 提交 </ button >
</ form >
<!-- 阻止右键菜单 -->
< div @click.right.prevent ="openMenu" > 右键菜单 </ div >
</ template >
6.3 按键修饰符
按键修饰符处理键盘和鼠标操作:
1
2
3
4
5
6
7
8
9
10
11
< template >
<!-- 回车键提交 -->
< input @keyup.enter ="submit" />
<!-- Ctrl + Enter -->
< textarea @keyup.ctrl.enter ="send" ></ textarea >
<!-- 精确按键组合 -- >
< button @click.ctrl.exact ="onCtrlClick" > Ctrl + 点击 </ button >
< button @click.exact ="onClick" > 仅点击 , 无修饰键 </ button >
</ template >
第 7 节 表单绑定
7.1 v-model 双向绑定
表单元素需要同时做两件事:把数据显示到输入框,用户输入时更新数据。
手动实现需要写两行代码:
1
< input :value = "text" @input ="event => text = event.target.value" />
Vue 提供了 v-model 简化成一行:
1
< input v-model = "text" />
完整示例:
1
2
3
4
5
6
7
8
< script setup lang = "ts" >
const message = ref ( '' )
</ script >
< template >
< p > 你输入的内容 : {{ message }}</ p >
< input v-model = "message" placeholder="输入文字" />
</ template >
7.2 修饰符
修饰符 作用 示例 .number自动转数字 <input v-model.number="age" />.trim去除首尾空格 <input v-model.trim="title" />.lazy失焦时同步,而非输入时 <input v-model.lazy="content" />
1
2
3
4
< template >
< input v -model .number =" age " type = "number" />
< input v -model .trim =" username " />
</ template >
模板语法是 Vue 3 中"视图层 “的核心。你现在可以:
用 {{ }} 和 : 显示数据 用 v-if 和 v-for 控制显示结构 用 @ 和 v-model 处理用户操作 但所有代码都写在一个文件里,代码会越来越长。
下一步:怎么把页面拆成独立的小块来管理?