Vue.js使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定到底层Vue实例的数据。Vue的模板语法简洁直观,易于学习和使用,是Vue.js声明式渲染的核心。
在底层实现上,Vue会将模板编译成虚拟DOM渲染函数。结合响应式系统,Vue能够智能地计算出最少需要重新渲染多少组件,并把DOM操作次数减到最少。
插值是Vue模板语法的基础,用于将数据绑定到DOM。Vue提供了多种插值方式:
最基本的数据绑定形式是使用"Mustache"语法(双大括号):
<div id="app">
<span>消息: {{ message }}</span>
</div>
new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
双大括号会将数据解释为普通文本,而非HTML。为了输出真正的HTML,需要使用v-html指令:
在网站上动态渲染任意HTML可能会非常危险,因为它很容易导致XSS攻击。请只对可信内容使用v-html,绝不要对用户提供的内容使用。
<div id="app2">
<p>使用双大括号: {{ rawHtml }}</p>
<p>使用v-html指令: <span v-html="rawHtml"></span></p>
</div>
new Vue({
el: '#app2',
data: {
rawHtml: '<span style="color: red">这是红色的HTML文本</span>'
}
});
使用双大括号: {{ rawHtml }}
使用v-html指令:
Mustache语法不能用在HTML属性上,对于属性绑定,应该使用v-bind指令:
<div id="app3">
<div v-bind:id="dynamicId">这个div有动态ID</div>
<!-- 简写形式 -->
<button :disabled="isButtonDisabled">按钮</button>
</div>
new Vue({
el: '#app3',
data: {
dynamicId: 'myDiv',
isButtonDisabled: true
}
});
按钮当前状态: {{ isButtonDisabled ? '禁用' : '启用' }}
Vue.js在数据绑定中支持完整的JavaScript表达式:
<div id="app4">
<p>数字: {{ number }}</p>
<p>数字加1: {{ number + 1 }}</p>
<p>是否显示: {{ ok ? '是' : '否' }}</p>
<p>反转消息: {{ message.split('').reverse().join('') }}</p>
<p>动态ID: {{ 'list-' + id }}</p>
</div>
new Vue({
el: '#app4',
data: {
number: 10,
ok: true,
message: 'Hello Vue',
id: 123
}
});
数字: {{ number }}
数字加1: {{ number + 1 }}
是否显示: {{ ok ? '是' : '否' }}
反转消息: {{ message.split('').reverse().join('') }}
动态ID: {{ 'list-' + id }}
每个绑定都只能包含单个表达式,所以下面的例子都不会生效:
{{ var a = 1 }} // 这是语句,不是表达式
{{ if (ok) { return message } }} // 流程控制也不会生效,请使用三元表达式
指令是带有v-前缀的特殊属性。指令的职责是,当表达式的值改变时,将其产生的连带影响响应式地作用于DOM。
一个Vue指令通常包含以下部分:
v-指令名:参数.修饰符="值"
bind、on、ifv-bind:href中的hrefv-on:submit.prevent中的preventv-bind:href="url"中的url动态绑定一个或多个属性,或一个组件prop到表达式。
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">
<!-- 绑定多个属性 -->
<div v-bind="{ id: someId, class: someClass }"></div>
绑定事件监听器,事件类型由参数指定。
<!-- 绑定点击事件 -->
<button v-on:click="doSomething">点击</button>
<!-- 缩写 -->
<button @click="doSomething">点击</button>
<!-- 绑定多个事件 -->
<button v-on="{ click: onClick, mouseover: onMouseOver }">按钮</button>
在表单输入和应用状态间创建双向绑定。
<input v-model="message" placeholder="输入消息">
<p>消息是: {{ message }}</p>
根据条件渲染元素。
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>
根据条件展示元素(通过切换display属性)。
<h1 v-show="ok">你好!</h1>
<!-- 注意:v-show不支持<template>元素 -->
基于源数据多次渲染元素或模板块。
<ul>
<li v-for="item in items" :key="item.id">
{{ item.text }}
</li>
</ul>
更新元素的textContent,类似于双大括号插值。
<span v-text="message"></span>
<!-- 等价于 -->
<span>{{ message }}</span>
更新元素的innerHTML。
<div v-html="htmlContent"></div>
| 特性 | v-if | v-show |
|---|---|---|
| 渲染方式 | 条件性地渲染元素,条件为假时元素不会被渲染到DOM中 | 始终渲染元素,只是通过CSS的display属性切换显示/隐藏 |
| 初始渲染开销 | 较低(如果初始条件为假,则不会渲染) | 较高(无论初始条件如何,都会渲染) |
| 切换开销 | 较高(需要销毁和重建元素) | 较低(只是切换CSS属性) |
| 使用场景 | 适合条件很少改变的场景 | 适合频繁切换显示/隐藏的场景 |
| 与v-else配合 | 支持 | 不支持 |
| 与<template>配合 | 支持 | 不支持 |
下面的演示展示了Vue模板语法的各种用法。尝试修改输入框内容或切换选项,观察模板的变化。
欢迎消息: {{ welcomeMessage }}
这段文字的颜色会根据选择变化
共有 {{ todos.length }} 个任务,其中 {{ completedCount }} 个已完成。
原始文本: {{ inputText }}
反转文本: {{ reversedText }}
文本长度: {{ textLength }}
大写文本: {{ uppercaseText }}
// 数据部分
data: {
title: 'Vue模板语法演示',
welcomeMessage: '欢迎学习Vue模板语法',
useCustomColor: false,
customColor: '#ff0000',
userType: 'guest',
newTodo: '',
todos: [
{ text: '学习Vue模板语法', completed: true },
{ text: '练习Vue指令', completed: false },
{ text: '创建Vue应用', completed: false }
],
inputText: '示例文本',
clickCount: 0
},
// 计算属性
computed: {
completedCount() {
return this.todos.filter(todo => todo.completed).length;
},
reversedText() {
return this.inputText.split('').reverse().join('');
},
textLength() {
return this.inputText.length;
},
uppercaseText() {
return this.inputText.toUpperCase();
}
},
// 方法
methods: {
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({
text: this.newTodo,
completed: false
});
this.newTodo = '';
}
},
toggleTodo(index) {
this.todos[index].completed = !this.todos[index].completed;
},
removeTodo(index) {
this.todos.splice(index, 1);
},
incrementCount() {
this.clickCount++;
},
resetCount() {
this.clickCount = 0;
},
showAlert(message) {
alert(message);
}
}
修饰符是以点号.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
用于v-on指令,处理DOM事件细节。
<!-- 阻止单击事件继续传播 -->
<a @click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form @submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a @click.stop.prevent="doThat"></a>
<!-- 添加事件监听器时使用事件捕获模式 -->
<div @click.capture="doThis">...</div>
<!-- 只当事件在该元素本身触发时触发回调 -->
<div @click.self="doThat">...</div>
<!-- 点击事件最多触发一次 -->
<a @click.once="doThis"></a>
监听键盘事件时,指定具体的按键。
<!-- 只有在key是Enter时调用submit方法 -->
<input @keyup.enter="submit">
<!-- 常用按键修饰符 -->
<input @keyup.enter="..."> <!-- Enter键 -->
<input @keyup.tab="..."> <!-- Tab键 -->
<input @keyup.delete="..."> <!-- 删除键 -->
<input @keyup.esc="..."> <!-- Esc键 -->
<input @keyup.space="..."> <!-- 空格键 -->
<!-- 也可以使用按键码,但已废弃 -->
<input @keyup.13="submit">
实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
<!-- 常用系统修饰键 -->
.ctrl .alt .shift .meta
改变v-model在输入事件中同步数据的方式。
<!-- 在"change"事件后同步,而不是"input"事件 -->
<input v-model.lazy="msg">
<!-- 自动将用户的输入值转为数值类型 -->
<input v-model.number="age" type="number">
<!-- 自动过滤用户输入的首尾空白字符 -->
<input v-model.trim="msg">
Vue为两个最常用的指令提供了特别的简写:
| 完整语法 | 简写 | 说明 |
|---|---|---|
v-bind:href |
:href |
属性绑定 |
v-bind:class |
:class |
类绑定 |
v-on:click |
@click |
事件绑定 |
v-on:keyup.enter |
@keyup.enter |
键盘事件绑定 |
v-bind="{ id: someId, class: someClass }" |
="{ id: someId, class: someClass }" |
绑定多个属性(对象语法) |
建议在项目中统一使用简写形式,因为它更简洁、更符合现代JavaScript开发习惯。但如果你是Vue新手,可以先使用完整形式,等熟悉后再切换到简写。
{{ }}语法,将数据绑定为纯文本v-html指令,但要小心XSS攻击风险v-bind指令(简写:),动态绑定HTML属性v-前缀的特殊属性,用于响应式地作用于DOMv-if、v-for、v-model、v-on、v-show等现在你已经掌握了Vue的模板语法,接下来我们将学习计算属性和侦听器,这是处理复杂逻辑和响应式数据变化的重要工具。