第一部分:Vue 3 基础入门
第7集:模板语法基础:插值与指令
Vue 3的模板语法是连接数据和视图的桥梁,它允许我们在HTML中嵌入动态内容和逻辑。在本集中,我们将学习Vue 3模板语法的基础,包括插值、指令、表达式等内容。
7.1 插值语法
插值是Vue模板中最基本的动态内容渲染方式,使用双大括号{{ }}包裹表达式。
7.1.1 文本插值
作用:将数据渲染为文本内容。
示例:
<template>
<div>
<h1>{{ message }}</h1>
<p>{{ count }}</p>
<p>{{ isActive ? '激活' : '未激活' }}</p>
<p>{{ user.name }} - {{ user.age }}</p>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const message = ref('Hello Vue 3!')
const count = ref(0)
const isActive = ref(true)
const user = reactive({
name: '张三',
age: 25
})
</script>特点:
- 会自动转义HTML标签,防止XSS攻击
- 支持JavaScript表达式
- 会响应数据变化,自动更新视图
7.1.2 原始HTML插值
作用:渲染原始HTML内容。
语法:使用v-html指令。
示例:
<template>
<div>
<p v-html="rawHtml"></p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const rawHtml = ref('<strong>这是粗体文本</strong>')
</script>注意事项:
- 谨慎使用,可能导致XSS攻击
- 只对可信内容使用,不要对用户输入使用
7.1.3 属性插值
作用:动态绑定HTML属性。
语法:使用v-bind指令或简写:。
示例:
<template>
<div>
<img v-bind:src="imageUrl" alt="图片">
<img :src="imageUrl" :alt="imageAlt">
<div :class="className"></div>
<button :disabled="isDisabled">禁用按钮</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const imageUrl = ref('https://example.com/image.jpg')
const imageAlt = ref('示例图片')
const className = ref('box')
const isDisabled = ref(true)
</script>特点:
- 可以绑定任何HTML属性
- 支持动态属性名(Vue 3.2+)
- 支持布尔属性
7.2 指令系统
指令是Vue模板中的特殊属性,以v-前缀开头,用于在DOM上应用特殊的响应式行为。
7.2.1 指令的基本语法
<element v-directive:argument.modifier="value"></element>v-directive:指令名称argument:指令参数modifier:指令修饰符value:指令值
7.2.2 常用指令
1. v-bind
作用:动态绑定属性。
示例:
<!-- 完整语法 -->
<a v-bind:href="url">链接</a>
<!-- 简写 -->
<a :href="url">链接</a>
<!-- 动态属性名 -->
<a :[attributeName]="url">链接</a>
<!-- 绑定对象 -->
<div v-bind="objectOfAttrs"></div>2. v-on
作用:绑定事件监听器。
示例:
<!-- 完整语法 -->
<button v-on:click="handleClick">点击</button>
<!-- 简写 -->
<button @click="handleClick">点击</button>
<!-- 带参数 -->
<button @click="handleClick('hello')">点击</button>
<!-- 访问事件对象 -->
<button @click="handleClickWithEvent($event)">点击</button>
<!-- 事件修饰符 -->
<button @click.stop="handleClick">阻止冒泡</button>
<button @click.prevent="handleSubmit">阻止默认行为</button>
<button @click.stop.prevent="handleClick">链式修饰符</button>
<button @click.once="handleClick">只触发一次</button>
<!-- 按键修饰符 -->
<input @keyup.enter="handleEnter">
<input @keyup.esc="handleEsc">
<input @keyup.tab="handleTab">
<!-- 系统修饰符 -->
<button @click.ctrl="handleCtrlClick">Ctrl+点击</button>
<button @click.alt="handleAltClick">Alt+点击</button>
<button @click.shift="handleShiftClick">Shift+点击</button>
<button @click.meta="handleMetaClick">Meta+点击</button>3. v-model
作用:实现表单元素和数据的双向绑定。
示例:
<!-- 文本输入 -->
<input v-model="message" type="text">
<p>{{ message }}</p>
<!-- 多行文本 -->
<textarea v-model="textarea"></textarea>
<!-- 复选框 -->
<input v-model="isChecked" type="checkbox">
<label>{{ isChecked ? '已选中' : '未选中' }}</label>
<!-- 多个复选框 -->
<input v-model="checkedFruits" type="checkbox" value="apple">苹果
<input v-model="checkedFruits" type="checkbox" value="banana">香蕉
<input v-model="checkedFruits" type="checkbox" value="orange">橙子
<p>选中的水果: {{ checkedFruits }}</p>
<!-- 单选按钮 -->
<input v-model="selectedFruit" type="radio" value="apple">苹果
<input v-model="selectedFruit" type="radio" value="banana">香蕉
<input v-model="selectedFruit" type="radio" value="orange">橙子
<p>选中的水果: {{ selectedFruit }}</p>
<!-- 下拉选择 -->
<select v-model="selectedOption">
<option value="">请选择</option>
<option value="option1">选项1</option>
<option value="option2">选项2</option>
<option value="option3">选项3</option>
</select>
<p>选中的选项: {{ selectedOption }}</p>
<!-- 修饰符 -->
<input v-model.lazy="message" type="text"> <!-- 失去焦点时更新 -->
<input v-model.number="age" type="number"> <!-- 转换为数字 -->
<input v-model.trim="username" type="text"> <!-- 去除首尾空格 -->4. v-if / v-else-if / v-else
作用:条件渲染。
示例:
<template>
<div>
<p v-if="score >= 90">优秀</p>
<p v-else-if="score >= 80">良好</p>
<p v-else-if="score >= 60">及格</p>
<p v-else>不及格</p>
<div v-if="isLoggedIn">
<p>欢迎,{{ username }}!</p>
<button @click="logout">退出登录</button>
</div>
<div v-else>
<button @click="login">登录</button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const score = ref(85)
const isLoggedIn = ref(false)
const username = ref('张三')
function login() {
isLoggedIn.value = true
}
function logout() {
isLoggedIn.value = false
}
</script>特点:
- 条件为真时才会渲染元素
- 会销毁和重建元素,触发完整的生命周期
v-else必须紧跟在v-if或v-else-if后面
5. v-show
作用:条件显示元素。
示例:
<template>
<div>
<p v-show="isVisible">这是显示的文本</p>
<button @click="toggleVisible">切换显示</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const isVisible = ref(true)
function toggleVisible() {
isVisible.value = !isVisible.value
}
</script>v-if vs v-show:
| 特性 | v-if | v-show |
|---|---|---|
| 渲染方式 | 条件为真时渲染,为假时销毁 | 始终渲染,通过CSS display控制显示/隐藏 |
| 性能开销 | 切换时开销大 | 初始渲染开销大 |
| 适用场景 | 条件不频繁切换 | 条件频繁切换 |
| 支持template | 是 | 否 |
| 支持v-else | 是 | 否 |
6. v-for
作用:列表渲染。
示例:
<template>
<div>
<!-- 遍历数组 -->
<h3>水果列表</h3>
<ul>
<li v-for="(fruit, index) in fruits" :key="fruit.id">
{{ index + 1 }}. {{ fruit.name }} - {{ fruit.price }}元
</li>
</ul>
<!-- 遍历对象 -->
<h3>用户信息</h3>
<ul>
<li v-for="(value, key, index) in user" :key="key">
{{ index + 1 }}. {{ key }}: {{ value }}
</li>
</ul>
<!-- 遍历数字 -->
<h3>数字列表</h3>
<ul>
<li v-for="n in 5" :key="n">
{{ n }}
</li>
</ul>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const fruits = ref([
{ id: 1, name: '苹果', price: 5.5 },
{ id: 2, name: '香蕉', price: 3.0 },
{ id: 3, name: '橙子', price: 4.0 }
])
const user = reactive({
name: '张三',
age: 25,
email: 'zhangsan@example.com'
})
</script>注意事项:
- 必须使用
key属性,并且值要唯一 key值不能是索引(除非列表不涉及排序、过滤等操作)- 不建议在同一元素上使用
v-if和v-for(Vue 3会报警告)
7.3 表达式支持
Vue模板支持JavaScript表达式,但有一些限制:
支持的表达式:
- 算术表达式:
{{ 1 + 1 }}、{{ count * 2 }} - 比较表达式:
{{ count > 0 }}、{{ count === 10 }} - 逻辑表达式:
{{ isActive && isVisible }}、{{ isActive || isVisible }} - 三元表达式:
{{ isActive ? '激活' : '未激活' }} - 对象和数组:
{{ { name: '张三' } }}、{{ [1, 2, 3] }} - 方法调用:
{{ message.toUpperCase() }}、{{ formatDate(date) }} - 模板字符串:
{{${user.name} - ${user.age}}}
不支持的表达式:
- 语句:
{{ if (isActive) { return '激活' } }}(使用三元表达式替代) - 声明:
{{ const a = 1 }}、{{ let b = 2 }}、{{ var c = 3 }} - 赋值:
{{ count = 1 }} - 副作用的表达式:
{{ console.log('hello') }}、{{ count++ }}
7.4 模板语法最佳实践
保持模板简洁:
- 模板中只放简单的表达式
- 复杂逻辑放在计算属性或方法中
- 避免在模板中写过多的JavaScript代码
合理使用指令:
- 根据场景选择合适的指令
- 优先使用简写语法(
:、@) - 合理使用修饰符
性能优化:
- 使用
v-memo优化频繁渲染的列表 - 使用
v-once优化静态内容 - 合理使用
v-if和v-show - 为
v-for提供唯一的key
- 使用
代码可读性:
- 指令按逻辑顺序排列
- 复杂的
v-bind或v-on可以拆分成多行 - 使用有意义的变量名和属性名
安全性:
- 避免使用
v-html渲染不可信内容 - 对用户输入进行验证和过滤
- 使用计算属性处理敏感数据
- 避免使用
本集小结
在本集中,我们学习了Vue 3模板语法的基础:
- 插值语法:文本插值、原始HTML插值、属性插值
- 指令系统:
v-bind:动态绑定属性v-on:绑定事件监听器v-model:双向数据绑定v-if/v-else-if/v-else:条件渲染v-show:条件显示v-for:列表渲染
- 表达式支持:支持的表达式类型和限制
- 最佳实践:保持模板简洁、合理使用指令、性能优化等
模板语法是Vue开发的基础,掌握好模板语法可以让我们更高效地开发Vue应用。在下一集中,我们将学习Vue 3的响应式数据,深入了解Vue的响应式系统。