v-if

在字符串模板中,如 Handlebars,我们得像这样写一个条件块:

<!– Handlebars 模板 –>
{{#if ok}}
<h1>Yes</h1>
{{/if}}
在 Vue.js,我们使用 v-if 指令实现同样的功能:

<h1 v-if=”ok”>Yes</h1>
也可以用 v-else 添加一个 “else” 块:

<h1 v-if=”ok”>Yes</h1>
<h1 v-else>No</h1>
template v-if

因为 v-if 是一个指令,需要将它添加到一个元素上。但是如果我们想切换多个元素呢?此时我们可以把一个 <template> 元素当做包装元素,并在上面使用 v-if,最终的渲染结果不会包含它。

<template v-if=”ok”>
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
v-show

另一个根据条件展示元素的选项是 v-show 指令。用法大体上一样:

<h1 v-show=”ok”>Hello!</h1>
不同的是有 v-show 的元素会始终渲染并保持在 DOM 中。v-show 是简单的切换元素的 CSS 属性 display。

注意 v-show 不支持 <template> 语法。

v-else

可以用 v-else 指令给 v-if 或 v-show 添加一个 “else 块”:

<div v-if=”Math.random() > 0.5″>
Sorry
</div>
<div v-else>
Not sorry
</div>
v-else 元素必须立即跟在 v-if 或 v-show 元素的后面——否则它不能被识别。

组件警告

将 v-show 用在组件上时,因为指令的优先级 v-else 会出现问题。因此不要这样做:

<custom-component v-show=”condition”></custom-component>
<p v-else>这可能也是一个组件</p>
用另一个 v-show 替换 v-else:

<custom-component v-show=”condition”></custom-component>
<p v-show=”!condition”>这可能也是一个组件</p>
这样就可以达到 v-if 的效果。

v-if vs. v-show

在切换 v-if 块时,Vue.js 有一个局部编译/卸载过程,因为 v-if 之中的模板也可能包括数据绑定或子组件。v-if 是真实的条件渲染,因为它会确保条件块在切换当中合适地销毁与重建条件块内的事件监听器和子组件。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始局部编译(编译会被缓存起来)。

相比之下,v-show 简单得多——元素始终被编译并保留,只是简单地基于 CSS 切换。

一般来说,v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换 v-show 较好,如果在运行时条件不大可能改变 v-if 较好。

数据绑定一个常见需求是操作元素的 class 列表和它的内联样式。因为它们都是 attribute,我们可以用 v-bind 处理它们:只需要计算出表达式最终的字符串。不过,字符串拼接麻烦又易错。因此,在 v-bind 用于 class 和 style 时,Vue.js 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组。

绑定 HTML Class

尽管可以用 Mustache 标签绑定 class,比如 class=”{{ className }}”,但是我们不推荐这种写法和 v-bind:class 混用。两者只能选其一!

对象语法

我们可以传给 v-bind:class 一个对象,以动态地切换 class。注意 v-bind:class 指令可以与普通的 class 特性共存:

<div class=”static” v-bind:class=”{ ‘class-a’: isA, ‘class-b’: isB }”></div>
data: {
isA: true,
isB: false
}
渲染为:

<div class=”static class-a”></div>
当 isA 和 isB 变化时,class 列表将相应地更新。例如,如果 isB 变为 true,class 列表将变为 “static class-a class-b”。

你也可以直接绑定数据里的一个对象:

<div v-bind:class=”classObject”></div>
data: {
classObject: {
‘class-a’: true,
‘class-b’: false
}
}
我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式。

数组语法

我们可以把一个数组传给 v-bind:class,以应用一个 class 列表:

<div v-bind:class=”[classA, classB]”>
data: {
classA: ‘class-a’,
classB: ‘class-b’
}
渲染为:

<div class=”class-a class-b”></div>
如果你也想根据条件切换列表中的 class,可以用三元表达式:

<div v-bind:class=”[classA, isB ? classB : ”]”>
此例始终添加 classA,但是只有在 isB 是 true 时添加 classB 。

不过,当有多个条件 class 时这样写有些繁琐。在 1.0.19+ 中,可以在数组语法中使用对象语法:

<div v-bind:class=”[classA, { classB: isB, classC: isC }]”>
绑定内联样式

对象语法

v-bind:style 的对象语法十分直观——看着非常像 CSS,其实它是一个 JavaScript 对象。CSS 属性名可以用驼峰式(camelCase)或短横分隔命名(kebab-case):

<div v-bind:style=”{ color: activeColor, fontSize: fontSize + ‘px’ }”></div>
data: {
activeColor: ‘red’,
fontSize: 30
}
直接绑定到一个样式对象通常更好,让模板更清晰:

<div v-bind:style=”styleObject”></div>
data: {
styleObject: {
color: ‘red’,
fontSize: ’13px’
}
}
同样的,对象语法常常结合返回对象的计算属性使用。

数组语法

v-bind:style 的数组语法可以将多个样式对象应用到一个元素上:

<div v-bind:style=”[styleObjectA, styleObjectB]”>
自动添加前缀

当 v-bind:style 使用需要厂商前缀的 CSS 属性时,如 transform,Vue.js 会自动侦测并添加相应的前缀。

在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作。模板是为了描述视图的结构。在模板中放入太多的逻辑会让模板过重且难以维护。这就是为什么 Vue.js 将绑定表达式限制为一个表达式。如果需要多于一个表达式的逻辑,应当使用计算属性。

基础例子

<div id=”example”>
a={{ a }}, b={{ b }}
</div>
var vm = new Vue({
el: ‘#example’,
data: {
a: 1
},
computed: {
// 一个计算属性的 getter
b: function () {
// `this` 指向 vm 实例
return this.a + 1
}
}
})
结果:

a=1, b=2
这里我们声明了一个计算属性 b。我们提供的函数将用作属性 vm.b的 getter。

console.log(vm.b) // -> 2
vm.a = 2
console.log(vm.b) // -> 3
你可以打开浏览器的控制台,修改 vm。vm.b 的值始终取决于 vm.a 的值。

你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.b 依赖于 vm.a,因此当 vm.a 发生改变时,依赖于 vm.b 的绑定也会更新。而且最妙的是我们是声明式地创建这种依赖关系:计算属性的 getter 是干净无副作用的,因此也是易于测试和理解的。

计算属性 vs. $watch

Vue.js 提供了一个方法 $watch,它用于观察 Vue 实例上的数据变动。当一些数据需要根据其它数据变化时, $watch 很诱人 —— 特别是如果你来自 AngularJS。不过,通常更好的办法是使用计算属性而不是一个命令式的 $watch 回调。考虑下面例子:

<div id=”demo”>{{fullName}}</div>
var vm = new Vue({
el: ‘#demo’,
data: {
firstName: ‘Foo’,
lastName: ‘Bar’,
fullName: ‘Foo Bar’
}
})

vm.$watch(‘firstName’, function (val) {
this.fullName = val + ‘ ‘ + this.lastName
})

vm.$watch(‘lastName’, function (val) {
this.fullName = this.firstName + ‘ ‘ + val
})
上面代码是命令式的重复的。跟计算属性对比:

var vm = new Vue({
el: ‘#demo’,
data: {
firstName: ‘Foo’,
lastName: ‘Bar’
},
computed: {
fullName: function () {
return this.firstName + ‘ ‘ + this.lastName
}
}
})
这样更好,不是吗?

计算 setter

计算属性默认只是 getter,不过在需要时你也可以提供一个 setter:

// …
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ‘ ‘ + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(‘ ‘)
this.firstName = names[0]
this.lastName = names[names.length – 1]
}
}
}
// …
现在在调用 vm.fullName = ‘John Doe’ 时,setter 会被调用,vm.firstName 和 vm.lastName 也会有相应更新。

数据绑定语法

Vue.js 的模板是基于 DOM 实现的。这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强。Vue 模板因而从根本上不同于基于字符串的模板,请记住这点。

插值

文本

数据绑定最基础的形式是文本插值,使用 “Mustache” 语法(双大括号):

<span>Message: {{ msg }}</span>
Mustache 标签会被相应数据对象的 msg 属性的值替换。每当这个属性变化时它也会更新。

你也可以只处理单次插值,今后的数据变化就不会再引起插值更新了:

<span>This will never change: {{* msg }}</span>
原始的 HTML

双 Mustache 标签将数据解析为纯文本而不是 HTML。为了输出真的 HTML 字符串,需要用三 Mustache 标签:

<div>{{{ raw_html }}}</div>
内容以 HTML 字符串插入——数据绑定将被忽略。如果需要复用模板片断,应当使用 partials。

在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。记住,只对可信内容使用 HTML 插值,永不用于用户提交的内容。

Read More →

构造器

每个 Vue.js 应用的起步都是通过构造函数 Vue 创建一个 Vue 的根实例:

var vm = new Vue({
// 选项
})
一个 Vue 实例其实正是一个 MVVM 模式中所描述的 ViewModel – 因此在文档中经常会使用 vm 这个变量名。

在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。全部的选项可以在 API 文档中查看。

可以扩展 Vue 构造器,从而用预定义选项创建可复用的组件构造器:

var MyComponent = Vue.extend({
// 扩展选项
})

// 所有的 `MyComponent` 实例都将以预定义的扩展选项被创建
var myComponentInstance = new MyComponent()
尽管可以命令式地创建扩展实例,不过在多数情况下将组件构造器注册为一个自定义元素,然后声明式地用在模板中。我们将在后面详细说明组件系统。现在你只需知道所有的 Vue.js 组件其实都是被扩展的 Vue 实例。

属性与方法

每个 Vue 实例都会代理其 data 对象里所有的属性:

var data = { a: 1 }
var vm = new Vue({
data: data
})

vm.a === data.a // -> true

// 设置属性也会影响到原始数据
vm.a = 2
data.a // -> 2

// … 反之亦然
data.a = 3
vm.a // -> 3

Read More →