Vue 模板语法
Vue 使用基于 HTML 的模板语法,允许你声明式地将 DOM 绑定到底层组件实例的数据。本章将详细介绍 Vue 的模板语法。
插值
文本插值
最基本的数据绑定形式是使用"Mustache"语法(双大括号):
<span>消息: {{ message }}</span>
当 message 属性改变时,模板中的内容会自动更新。
一次性插值
如果你想只渲染一次,之后不随数据更新,可以使用 v-once 指令:
<span v-once>这个消息不会改变: {{ message }}</span>
原始 HTML
双大括号会将数据作为普通文本渲染,而不是 HTML。要输出真正的 HTML,需要使用 v-html 指令:
<p>使用双大括号: {{ rawHtml }}</p>
<p>使用 v-html: <span v-html="rawHtml"></span></p>
<script setup>
const rawHtml = '<span style="color: red">这是红色文字</span>'
</script>
安全提示:在你的站点上动态渲染任意的 HTML 是非常危险的,容易导致 XSS 攻击。只在可信内容上使用
v-html,不要在用户提交的内容上使用。
JavaScript 表达式
Vue 模板支持在插值中使用 JavaScript 表达式:
<!-- 数学运算 -->
<p>{{ number + 1 }}</p>
<!-- 三元运算符 -->
<p>{{ ok ? '是' : '否' }}</p>
<!-- 字符串方法 -->
<p>{{ message.split('').reverse().join('') }}</p>
<!-- 函数调用 -->
<p>{{ new Date().toLocaleDateString() }}</p>
<script setup>
const number = ref(10)
const ok = ref(true)
const message = ref('Hello')
</script>
指令
指令是带有 v- 前缀的特殊属性。指令的职责是当表达式的值改变时,产生相应的响应式行为。
v-bind
v-bind 指令用于动态绑定 HTML 属性:
<!-- 绑定 class -->
<p :class="{ active: isActive }">动态class</p>
<!-- 绑定 style -->
<p :style="{ color: textColor, fontSize: fontSize + 'px' }">动态style</p>
<!-- 绑定 src -->
<img :src="imageUrl" alt="图片" />
<!-- 绑定 href -->
<a :href="url">链接</a>
<script setup>
const isActive = ref(true)
const textColor = ref('blue')
const fontSize = ref(18)
const imageUrl = ref('https://vuejs.org/logo.png')
const url = ref('https://vuejs.org')
</script>
简写形式
v-bind 可以简写为 ::
<!-- 完整写法 -->
<img v-bind:src="imageUrl" />
<!-- 简写 -->
<img :src="imageUrl" />
v-on
v-on 指令用于绑定事件监听器:
<!-- 绑定 click 事件 -->
<button v-on:click="handleClick">点击</button>
<!-- 简写形式 -->
<button @click="handleClick">点击</button>
<!-- 传递参数 -->
<button @click="greet('Hello')">问候</button>
<script setup>
function handleClick() {
console.log('按钮被点击')
}
function greet(message) {
alert(message)
}
</script>
事件修饰符
Vue 提供了事件修饰符来简化常见需求:
<!-- .stop - 阻止事件继续传播 -->
<button @click.stop="handleClick">点击</button>
<!-- .prevent - 阻止默认行为 -->
<form @submit.prevent="handleSubmit">...</form>
<!-- .capture - 使用捕获模式 -->
<div @click.capture="handleClick">...</div>
<!-- .self - 只有事件目标是当前元素时触发 -->
<div @click.self="handleClick">...</div>
<!-- .once - 只触发一次 -->
<button @click.once="handleClick">点击</button>
<!-- .passive - 监听器使用 passive 模式 -->
<div @scroll.passive="handleScroll">...</div>
v-model
v-model 用于创建双向数据绑定:
<!-- 文本输入 -->
<input v-model="message" />
<p>{{ message }}</p>
<!-- 复选框 -->
<input type="checkbox" v-model="checked" />
<p>{{ checked ? '已勾选' : '未勾选' }}</p>
<!-- 单选按钮 -->
<input type="radio" value="one" v-model="choice" />
<input type="radio" value="two" v-model="choice" />
<p>选择了: {{ choice }}</p>
<!-- 下拉选择 -->
<select v-model="selected">
<option value="">请选择</option>
<option value="a">选项 A</option>
<option value="b">选项 B</option>
</select>
<script setup>
import { ref } from 'vue'
const message = ref('Hello')
const checked = ref(true)
const choice = ref('one')
const selected = ref('')
</script>
v-model 修饰符
<!-- .lazy - 失去焦点时更新(默认是 input 事件) -->
<input v-model.lazy="message" />
<!-- .number - 自动转换为数字 -->
<input v-model.number="age" />
<!-- .trim - 去除首尾空格 -->
<input v-model.trim="username" />
v-if / v-else / v-else-if
条件渲染根据表达式的值决定是否渲染元素:
<h1 v-if="awesome">Vue 很棒!</h1>
<h1 v-else>哦不 =(</h1>
<!-- v-else-if -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>其他</div>
v-show
v-show 用于条件显示元素(始终渲染,只是切换 CSS 的 display 属性):
<h1 v-show="ok">你好!</h1>
v-for
列表渲染,使用 v-for 指令:
<!-- 遍历数组 -->
<li v-for="item in items">{{ item }}</li>
<!-- 遍历数组,带索引 -->
<li v-for="(item, index) in items">{{ index }} - {{ item }}</li>
<!-- 遍历对象 -->
<li v-for="value in object">{{ value }}</li>
<!-- 遍历对象,带键和索引 -->
<li v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</li>
<script setup>
const items = ref(['苹果', '香蕉', '橙子'])
const object = ref({
name: '张三',
age: 25,
city: '北京'
})
</script>
v-text 和 v-html
v-text:更新元素的文本内容v-html:更新元素的 HTML 内容
<span v-text="message"></span>
<span v-html="rawHtml"></span>
计算属性
计算属性是基于响应式依赖进行缓存的属性,只有当依赖变化时才会重新计算。
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('张')
const lastName = ref('三')
// 计算属性
const fullName = computed(() => {
return firstName.value + lastName.value
})
</script>
<template>
<p>姓: {{ firstName }}</p>
<p>名: {{ lastName }}</p>
<p>全名: {{ fullName }}</p>
</template>
计算属性的特点:
- 缓存:依赖不变时,不会重新计算
- 响应式:依赖变化时,自动更新
- 可写:通过 get 和 set 定义可写的计算属性
const fullName = computed({
get() {
return firstName.value + lastName.value
},
set(value) {
firstName.value = value[0]
lastName.value = value.slice(1)
}
})
小结
本章我们学习了 Vue 模板语法的主要内容:
- 插值语法:
{{ }}显示数据 - 指令系统:v-bind、v-on、v-model、v-if、v-for 等
- 事件修饰符:.stop、.prevent 等
- v-model 修饰符:.lazy、.number、.trim
- 计算属性:基于依赖的缓存计算
练习
- 创建一个待办事项列表,使用 v-for 渲染
- 使用计算属性实现搜索过滤功能
- 尝试使用 v-html 渲染带有样式的 HTML 内容
准备好进入下一章,学习条件渲染的详细内容了吗?