模板语法
Vue.js
使用了基于 HTML
的模版语法,允许开发者声明式地将 DOM
绑定至底层 Vue
实例的数据。所有 Vue.js
的模板都是合法的 HTML
,所以能被遵循规范的浏览器和 HTML
解析器解析。
在底层的实现上,Vue
将模板编译成虚拟 DOM
渲染函数。结合响应系统,Vue
能够智能地计算出最少需要重新渲染多少组件,并把 DOM
操作次数减到最少。
如果你熟悉虚拟 DOM
并且偏爱 JavaScript
的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX
语法。
如何插值
文本
文本中数据绑定最常见的形式就是使用 {{}}
“Mustache”语法(双大括号),双大括号中间的内容是 data
里面的数据,可以是变量或者是表达式。
示例:
我们来看一个示例,在项目的 main.js
文件中创建一个 Vue
实例,定义一个 msg
数据 :
import { createApp } from 'vue'
const vm = Vue.createApp({
data() {
return {
msg:'你好,侠课岛!'
}
}
}).mount('#app')
然后在 index.html
文件中通过双大括号绑定 msg
:
<div id="app">
<span>文本内容: {{ msg }}</span>
</div>
上述双大括号将会被代替为对应组件实例中 msg
属性的值,无论何时,当绑定的数据对象上的 msg
属性值发生改变,插值处的内容就会更新。
通过使用 v-once
指令,我们也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
<div id="app">
<span v-once>这个将不会改变: {{ msg }}</span>
</div>
原始HTML
注意双大括号 {{}}
会将数据解释为普通文本,而非 HTML
代码。为了输出真正的 HTML
,我们需要使用 v-html
指令。
示例:
下面我们来看一下,使用双大括号和 v-html
指令这两种方式来显示 HTML
代码,会有什么不同。
在 index.html
文件中写入代码
<div id="app">
<p>使用双大括号显示内容: {{ rawHtml }}</p>
<p>使用v-html指令显示内容: <span v-html="rawHtml"></span></p>
</div>
在 main.js
文件写入代码:
import { createApp } from 'vue'
const HelloVueApp = {
data() {
return {
rawHtml: '<span style="color: pink">这里字体应该是粉色的</span>'
}
}
}
Vue.createApp(HelloVueApp).mount('#app')
刷新浏览器,如下图所示:
可以看到,使用双大括号显示的是普通文本,而 v-html
指令输出了真正的 HTML
代码,并且字体颜色变为了粉色。
注意我们不能使用 v-html
来复合局部模板,因为 Vue
不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。
提示:在你的站点上动态渲染任意的 HTML 是非常危险的,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。
HTML属性绑定
Mustache
(双大括号)语法不能在 HTML
属性中使用,我们可以使用 v-bind
指令来将 data
里面的数据绑定到元素的属性上,例如 id
、class
、style
、href
等属性。
示例:
例如使用 v-bind
指令将数据绑定到 <div>
元素的 id
属性上:
<div id="app">
<div v-bind:id="dynamicId"></div>
</div>
对于布尔属性(它们只要存在就意味着值为 true
),v-bind
指令工作起来略有不同,例如:
<button v-bind:disabled="isButtonDisabled">按钮</button>
如果 isButtonDisabled
的值是 null
或 undefined
,则 disabled
属性甚至不会被包含在渲染出来的 <button>
元素中。
使用 JavaScript 表达式
在 Vue.js
中我们可以在模板中绑定简单的属性键值,而对于所有的数据绑定,Vue.js
都提供了完全的 JavaScript
表达式支持。
例如下面这些表达式在所属 Vue
实例的数据作用域下作为 JavaScript
被解析:
{{ count + 1 }}
{{ ok ? 'YES' : 'NO' }}
<div v-bind:id="'list-' + id"></div>
但是这有一个限制,就是每个绑定都只能包含单个表达式,否则不会生效。
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
指令的使用
指令 (Directives) 是带有 v-
前缀的特殊属性。指令属性的值预期是单个 JavaScript
表达式 (v-for
和 v-on
是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
。
示例:
看下面这个例子:
<div id="app">
<p v-if="seen">现在你看到我了</p>
</div>
上述代码中的 v-if
指令将根据表达式 seen
的值的真假来插入或移除 <p>
元素。
例如我们在 Vue
实例中将 seen
的值设置为 true
:
import { createApp } from 'vue'
const HelloVueApp = {
data() {
return {
seen:true
}
}
}
Vue.createApp(HelloVueApp).mount('#app')
演示效果如下所示:
可以看到,<p>
元素的内容成功渲染到浏览器页面,但是如果我们将 seen
的值设置为 false
,则 <p>
元素会被隐藏。
参数
一些指令能够接收一个参数,在指令名称之后以 :
冒号的形式表示。例如 v-bind
指令可以用于响应式地更新 HTML
属性:
<div v-bind:id="id" v-bind:class="class" v-bind:title="title"></div>
上述中的 id
、class
、title
都是参数,告知 v-bind
指令将该元素的属性与表达式对应的值绑定。
另一个例子是 v-on
指令,它用于监听 DOM
事件,例如:
<a v-on:click="doSomething"> ... </a>
动态参数
我们也可以在指令参数中使用 JavaScript
表达式,方法是用方括号括起来:
<a v-bind:[attributeName]="url"> ... </a>
这里的 attributeName
会被作为一个 JavaScript
表达式进行动态求值,求得的值将会作为最终的参数来使用。例如如果组件实例有一个 data
属性attributeName
,其值为 "href"
,那么这个绑定将等价于 v-bind:href
。
同样地,我们可以使用动态参数为一个动态的事件名绑定处理函数:
<a v-on:[eventName]="doSomething"> ... </a>
在这个示例中,当 eventName
的值为 "focus"
时,v-on:[eventName]
将等价于 v-on:focus
。
修饰符
修饰符 (modifier) 是以半角句号 .
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
示例:
<form v-on:submit.prevent="onSubmit">...</form>
上述 .prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
。
缩写
v-
前缀作为一种视觉提示,用来识别模板中 Vue
特定的属性。当我们在使用 Vue.js
为现有标签添加动态行为 (dynamic behavior) 时,v-
前缀很有帮助,然而对于一些频繁用到的指令来说,就会感到使用繁琐。同时,在构建由 Vue
管理所有模板的单页面应用程序 (SPA - single page application)时,v-
前缀也变得没那么重要了。因此 Vue
为 v-bind
和 v-on
这两个最常用的指令,提供了特定简写:
v-bind
的缩写形式:
<!-- 完整语法 -->
<a v-bind:href="url"> ... </a>
<!-- 缩写 -->
<a :href="url"> ... </a>
<!-- 动态参数的缩写 -->
<a :[key]="url"> ... </a>
v-on
的缩写形式:
<!-- 完整语法 -->
<a v-on:click="doSomething"> ... </a>
<!-- 缩写 -->
<a @click="doSomething"> ... </a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
它们看起来可能与普通的 HTML
略有不同,但 :
与 @
对于 attribute
名来说都是合法字符,在所有支持 Vue
的浏览器都能被正确地解析。而且它们不会出现在最终渲染的标记中。缩写语法是完全可选的,可以选择使用或者不使用。
注意事项
对动态参数值约定
动态参数预期会求出一个字符串,异常情况下值为 null
。这个特殊的 null
值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。
对动态参数表达式约定
动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的。例如:
<!-- 这会触发一个编译警告 -->
<a v-bind:['foo' + bar]="value"> ... </a>
变通的办法是使用没有空格或引号的表达式,或用计算属性替代这种复杂表达式。
在 DOM
中使用模板时 (直接在一个 HTML
文件里撰写模板),还需要避免使用大写字符来命名键名,因为浏览器会把 attribute
名全部强制转为小写:
<!--
在 DOM 中使用模板时这段代码会被转换为 `v-bind:[someattr]`。
除非在实例中有一个名为“someattr”的 property,否则代码不会工作。
-->
<a v-bind:[someAttr]="value"> ... </a>
JavaScript 表达式
模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math
和 Date
。我们不应该在模板表达式中试图访问用户定义的全局变量。