跳到主要内容

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>

计算属性的特点:

  1. 缓存:依赖不变时,不会重新计算
  2. 响应式:依赖变化时,自动更新
  3. 可写:通过 get 和 set 定义可写的计算属性
const fullName = computed({
get() {
return firstName.value + lastName.value
},
set(value) {
firstName.value = value[0]
lastName.value = value.slice(1)
}
})

小结

本章我们学习了 Vue 模板语法的主要内容:

  1. 插值语法{{ }} 显示数据
  2. 指令系统:v-bind、v-on、v-model、v-if、v-for 等
  3. 事件修饰符:.stop、.prevent 等
  4. v-model 修饰符:.lazy、.number、.trim
  5. 计算属性:基于依赖的缓存计算

练习

  1. 创建一个待办事项列表,使用 v-for 渲染
  2. 使用计算属性实现搜索过滤功能
  3. 尝试使用 v-html 渲染带有样式的 HTML 内容

准备好进入下一章,学习条件渲染的详细内容了吗?