Vue.js模板语法

Vue.js使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定到底层Vue实例的数据。Vue的模板语法简洁直观,易于学习和使用,是Vue.js声明式渲染的核心。

在底层实现上,Vue会将模板编译成虚拟DOM渲染函数。结合响应式系统,Vue能够智能地计算出最少需要重新渲染多少组件,并把DOM操作次数减到最少。

插值(Interpolation)

插值是Vue模板语法的基础,用于将数据绑定到DOM。Vue提供了多种插值方式:

1. 文本插值(Mustache语法)

最基本的数据绑定形式是使用"Mustache"语法(双大括号):

HTML模板

<div id="app">
  <span>消息: {{ message }}</span>
</div>
                                
JavaScript代码

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
});
                                
消息: {{ message }}

2. 原始HTML插值(v-html指令)

双大括号会将数据解释为普通文本,而非HTML。为了输出真正的HTML,需要使用v-html指令:

注意:安全风险

在网站上动态渲染任意HTML可能会非常危险,因为它很容易导致XSS攻击。请只对可信内容使用v-html,绝不要对用户提供的内容使用。

HTML模板

<div id="app2">
  <p>使用双大括号: {{ rawHtml }}</p>
  <p>使用v-html指令: <span v-html="rawHtml"></span></p>
</div>
                                
JavaScript代码

new Vue({
  el: '#app2',
  data: {
    rawHtml: '<span style="color: red">这是红色的HTML文本</span>'
  }
});
                                

使用双大括号: {{ rawHtml }}

使用v-html指令:

3. 属性绑定(v-bind指令)

Mustache语法不能用在HTML属性上,对于属性绑定,应该使用v-bind指令:

HTML模板

<div id="app3">
  <div v-bind:id="dynamicId">这个div有动态ID</div>
  <!-- 简写形式 -->
  <button :disabled="isButtonDisabled">按钮</button>
</div>
                                
JavaScript代码

new Vue({
  el: '#app3',
  data: {
    dynamicId: 'myDiv',
    isButtonDisabled: true
  }
});
                                
这个div有动态ID,检查元素可以看到id="{{ dynamicId }}"

按钮当前状态: {{ isButtonDisabled ? '禁用' : '启用' }}

4. 使用JavaScript表达式

Vue.js在数据绑定中支持完整的JavaScript表达式:

HTML模板

<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>
                                
JavaScript代码

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 } }}  // 流程控制也不会生效,请使用三元表达式
                            

指令(Directives)

指令是带有v-前缀的特殊属性。指令的职责是,当表达式的值改变时,将其产生的连带影响响应式地作用于DOM。

指令结构

一个Vue指令通常包含以下部分:

v-指令名:参数.修饰符="值"

  • 指令名: 指令的名称,如bindonif
  • 参数: 在指令名后以冒号表示,如v-bind:href中的href
  • 修饰符: 以点号指明的特殊后缀,如v-on:submit.prevent中的prevent
  • : 指令的绑定值,如v-bind:href="url"中的url

常用指令

v-bind 缩写: :

动态绑定一个或多个属性,或一个组件prop到表达式。


<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">

<!-- 绑定多个属性 -->
<div v-bind="{ id: someId, class: someClass }"></div>
                                    
v-on 缩写: @

绑定事件监听器,事件类型由参数指定。


<!-- 绑定点击事件 -->
<button v-on:click="doSomething">点击</button>
<!-- 缩写 -->
<button @click="doSomething">点击</button>

<!-- 绑定多个事件 -->
<button v-on="{ click: onClick, mouseover: onMouseOver }">按钮</button>
                                    
v-model

在表单输入和应用状态间创建双向绑定。

数据 视图

<input v-model="message" placeholder="输入消息">
<p>消息是: {{ message }}</p>
                                    
v-if / v-else-if / v-else

根据条件渲染元素。


<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>
                                    
v-show

根据条件展示元素(通过切换display属性)。


<h1 v-show="ok">你好!</h1>
<!-- 注意:v-show不支持<template>元素 -->
                                    
v-for

基于源数据多次渲染元素或模板块。


<ul>
  <li v-for="item in items" :key="item.id">
    {{ item.text }}
  </li>
</ul>
                                    
v-text

更新元素的textContent,类似于双大括号插值。


<span v-text="message"></span>
<!-- 等价于 -->
<span>{{ message }}</span>
                                    
v-html

更新元素的innerHTML。


<div v-html="htmlContent"></div>
                                    

v-if 与 v-show 的区别

特性 v-if v-show
渲染方式 条件性地渲染元素,条件为假时元素不会被渲染到DOM中 始终渲染元素,只是通过CSS的display属性切换显示/隐藏
初始渲染开销 较低(如果初始条件为假,则不会渲染) 较高(无论初始条件如何,都会渲染)
切换开销 较高(需要销毁和重建元素) 较低(只是切换CSS属性)
使用场景 适合条件很少改变的场景 适合频繁切换显示/隐藏的场景
与v-else配合 支持 不支持
与<template>配合 支持 不支持

模板语法综合演示

下面的演示展示了Vue模板语法的各种用法。尝试修改输入框内容或切换选项,观察模板的变化。

{{ title }}

欢迎消息: {{ welcomeMessage }}

这段文字的颜色会根据选择变化

条件渲染示例
欢迎管理员!您有所有权限。
欢迎用户!您有部分权限。
欢迎访客!您只有查看权限。
待办事项列表
  • {{ todo.text }}

共有 {{ 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);
  }
}
                            

修饰符(Modifiers)

修饰符是以点号.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。

事件修饰符

用于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修饰符

改变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新手,可以先使用完整形式,等熟悉后再切换到简写。

本章总结

  • 文本插值使用双大括号{{ }}语法,将数据绑定为纯文本
  • 原始HTML插值使用v-html指令,但要小心XSS攻击风险
  • 属性绑定使用v-bind指令(简写:),动态绑定HTML属性
  • 指令是带有v-前缀的特殊属性,用于响应式地作用于DOM
  • 表达式在插值和指令中使用,但必须是单个JavaScript表达式
  • 修饰符以点号表示,用于指定指令的特殊行为
  • 常用指令包括v-ifv-forv-modelv-onv-show
  • 理解模板语法是使用Vue的基础,后续的组件、路由等概念都建立在模板语法之上

下一步:计算属性与侦听器

现在你已经掌握了Vue的模板语法,接下来我们将学习计算属性和侦听器,这是处理复杂逻辑和响应式数据变化的重要工具。