# Vue模板语法
# 概述
Vue.js使用了基于HTML的模板语法,允许声明式地将DOM绑定至底层Vue实例的数据。 所有Vue.js的模板都是合法的HTML ,所以能被遵循规范的浏览器和HTML解析器解析。
在底层的实现上, Vue将模板编译成虚拟DOM渲染函数。 结合响应系统,在应用状态改变时, Vue能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上
一般地,模板内容包括文本内容和元素特性
# 文本渲染
# 文本插值
文本渲染最常见的形式是使用双大括号语法来进行文本插值
<div id="app">
<!-- message相当于一个变量或占位符,最终会表示为真正的文本内容 -->
{{ message }}
</div>
# 表达式插值
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
上面这些表达式会在所属Vue实例的数据作用域下作为JS被解析
WARNING
有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
# v-text
实现插值类似效果的另一种写法是使用v-text指令,该指令用于更新元素的innerText。
WARNING
如果要更新部分的innerText,需要使用模板插值
[注意] v-text优先级高于模板插值的优先级
<div id="app" v-text="message"></div>
data(){
message:'hello world!'
}
# v-html
如果要输出真正的 原始HTML
,需要使用 v-html
指令,该指令用于更新元素的 innerHTML
WARNING
[注意] 在网站上动态渲染任意 HTML
是非常危险的,因为容易导致 XSS 攻击。
只在可信内容上使用 v-html,而不用在用户提交的内容上
<div id="app" v-html="message"></div>
data(){
message:'<h1>this is v-html directive</h1>'
}
# 静态插值
一般地,模板插值是动态插值。即无论何时,绑定的数据对象上的占位符内容发生了改变,插值处的内容都会更新
# v-once
如果要实现静态插值,即执行一次性插值,数据改变时,插值处内容不会更新,这时需要用到v-once指令
<div id="app" v-once>{{ message }}</div>
data(){
message: '测试内容'
}
无论message的值如何变化,DOM结构中元素内容仍然是“测试内容”。
# 不解析渲染v-pre
如果要跳过这个元素和它的子元素的编译过程,只用来显示原始大括号及标识符,则可以使用v-pre指令。可以减少编译时间
<div id="app" v-pre>{{ message }}</div>
<!-- 界面仅显示{{ message }} -->
# 隐藏未编译v-clock
TIP
一般地,使用模板差值时,页面上会显示大括号及占位符。编译完成后,再转换为真正的值。如果在网络条件不好的情况下,这种现象更加明显
这个指令保持在元素上直到关联实例结束编译。
和 CSS 规则如 [v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache
标签直到实例准备完毕
<style>
[v-cloak]{display:none;}
</style>
<div id="example" v-cloak>{{ message }}</div>
# 特性渲染v-bind
v-bind指令可以动态地绑定一个或多个特性
<div id="app" v-bind:title="message"></div>
<!-- 缩写 -->
<div id="app" :title="message"></div>
data(){
message:"hello vue!"
}
# class绑定
数据绑定一个常见需求是操作元素的class列表和它的内联样式。 因为它们都是属性 ,可以用v-bind处理它们:只需要计算出表达式最终的字符串。 不过,字符串拼接麻烦又易错。因此,在v-bind用于class和style时, Vue.js 专门增强了它。 表达式的结果类型除了字符串之外,还可以是对象或数组
# 对象语法
我们可以传给 v-bind:class 一个对象,以动态地切换 class:
<!-- 1、内联对象语法 -->
<div v-bind:class="{ active: isActive }"></div>
<!-- 渲染结果 -->
<div class="active"></div>
<!-- 2、传入多个 -->
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
<!-- 渲染结果 -->
<div class="static active"></div>
<!-- 3、非内联绑定对象 -->
<div :class="classObject"></div>
<!-- 渲染结果 -->
<div class="static active"></div>
<!-- 4、绑定一个返回对象的计算属性 -->
<div :class="innerClassObject"></div>
<!-- 渲染结果 -->
<div class="static active"></div>
data() {
isActive: true,
hasError: false,
error: null,
// 非内联绑定对象
classObject: {
active: true,
'text-danger': false
}
}
computed: {
innerClassObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
# 数组语法
可以把一个数组传给 v-bind:class,以应用一个 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
<!-- 渲染为 -->
<div class="active text-danger"></div>
data(){
activeClass: 'active',
errorClass: 'text-danger'
}
# style绑定
# 对象语法
v-bind:style
的对象语法十分直观——看着非常像 CSS,但其实是一个JavaScript
对象。CSS property
名可以用驼峰式(camelCase)
或短横线分隔(kebab-case
,记得用引号括起来) 来命名
<!--
data: {
activeColor: 'red',
fontSize: 30,
styleObject:{
color: 'red',
fontSize: '13px'
}
}
-->
<!-- 1、内联对象 -->
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<!-- 2、直接绑定到一个样式对象通常更好,这会让模板更清晰 -->
<div v-bind:style="styleObject"></div>
<!-- 3、对象语法常常结合返回对象的计算属性使用。 -->
# 数组语法
v-bind:style 的数组语法可以将多个样式对象应用到一个元素上
<div id="app" :style="[baseStyles, overridingStyles]"></div>
data: {
baseStyles: {
color: 'red',
fontSize: '13px'
},
overridingStyles:{
height:'100px',
width:'100px'
}
}
# 前缀
当v-bind:style
使用需要特定前缀的CSS属性时,如transform
,Vue.js
会自动侦测并添加相应的前缀。
可以为 style
绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值。
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">
这会渲染数组中最后一个被浏览器支持的值。在这个例子中,如果浏览器支持不带浏览器前缀的 flexbox
,那么渲染结果会是 display: flex
# 过滤器
Vue.js允许自定义过滤器,可被用作一些常见的文本格式化。
过滤器可以用在两个地方:模板插值和v-bind表达式。过滤器应该被添加在JS表达式的尾部,由“管道”符 即 |
指示
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
# 组件的选项中局部过滤器
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
# 全局定义过滤器
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
// ...
})
WARNING
当全局过滤器和局部过滤器重名时,会采用局部过滤器。
# 过滤器可以串联
{{ message | filterA | filterB }}
filterA
被定义为接收单个参数的过滤器函数,表达式 message
的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB
,将 filterA
的结果传递到 filterB
中。
# 过滤器可以接收参数
{{ message | filterA('arg1', arg2) }}
filterA
被定义为接收三个参数的过滤器函数。其中 message
的值作为第一个参数,普通字符串 arg1
作为第二个参数,表达式 arg2
的值作为第三个参数。