从这一节开始,就开始正式的细节性、系统性的学习Vue.js!
Vue实例
构造器
每个 Vue.js 应用的起步都是通过构造函数 Vue
创建一个 Vue 的根实例:
<textarea readonly="readonly" name="code" class="javascript">
var vm = new Vue({
// 选项
})
</textarea>
一个 Vue 实例其实正是一个 MVVM 模式中所描述的 ViewModel - 因此在文档中经常会使用 vm
这个变量名。
在实例化 Vue 时,需要传入一个选项对象,它可以包含数据、模板、挂载元素、方法、生命周期钩子等选项。全部的选项可以在 API 文档中查看。可以扩展 Vue
构造器,从而用预定义选项创建可复用的组件构造器:
<textarea readonly="readonly" name="code" class="javascript">
var MyComponent = Vue.extend({
// 扩展选项
})
// 所有的 `MyComponent` 实例都将以预定义的扩展选项被创建
var myComponentInstance = new MyComponent()
</textarea>
注意:尽管可以命令式地创建扩展实例,不过在多数情况下将组件构造器注册为一个自定义元素,然后声明式地用在模板中。
现在你只需知道所有的 Vue.js 组件其实都是被扩展的 Vue 实例。
属性和方法
每个 Vue 实例都会代理其 data
对象里所有的属性:
<textarea readonly="readonly" name="code" class="javascript">
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
</textarea>
只有这些被代理的属性是响应的。如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。
除此之外,Vue实例暴露了一些有用的实例属性和方法,这些属性与方法都有前缀$,便于区分代理的数据属性。例如:
<textarea readonly="readonly" name="code" class="javascript">
.var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})
vm.$data === data // -> true
vm.$el === document.getElementById('example') // -> true
// $watch 是一个实例方法
vm.$watch('a', function (newVal, oldVal) {
// 这个回调将在 `vm.a` 改变后调用
})
</textarea>
实例生命周期
Vue 实例在创建时有一系列初始化步骤——例如,它需要建立数据观察,编译模板,创建必要的数据绑定。在此过程中,它也将调用一些生命周期钩子,给自定义逻辑提供运行机会。
例如:created 钩子在实例创建后调用:
<textarea readonly="readonly" name="code" class="javascript">
var vm = new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// -> "a is: 1"
</textarea>
也有一些其它的钩子,在实例生命周期的不同阶段调用,如 compiled
、 ready
、destroyed
。
钩子的 this
指向调用它的 Vue 实例。
有人可能会问 Vue.js 是否有“控制器”的概念?答案是,没有。组件的自定义逻辑可以分割在这些钩子中。
数据绑定语法
Vue.js 的模板是基于 DOM 实现的。这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强。Vue 模板因而从根本上不同于基于字符串的模板,请记住这点。
差值
文本:数据绑定最基础的形式是文本差值,使用双花括号({{message}}),每当这个属性变化时message也会更新。
<span>Message:{{message}}</span>
同时,也可以只处理单次差值,今后的数据变化就不会再引起差值更新了:
<span>This will never change:{{*message}}</span>
原始的HTML:双花括号标签将数据解析为纯文本而不是HTML,为了输出真的HTML字符串,需要用三标签:
<div>{{{raw_html}}}</div>
HTML 特性:双标签可以用在HTML特性内
<div id="item-{{id}}"></div>
注意:在 Vue.js 指令和特殊特性内不能用插值。
绑定表达式
放在 双标签内的文本称为绑定表达式。在 Vue.js 中,一段绑定表达式由一个简单的 JavaScript 表达式和可选的一个或多个过滤器构成。
*有一个限制就是:每个绑定只能包含单个表达式。
过滤器:
Vue.js 允许在表达式后添加可选的“过滤器 (Filter) ”,以“管道符”指示:
{{message | capitalize}}
这里我们将表达式 message
的值“管输(pipe)”到内置的 capitalize
过滤器,这个过滤器其实只是一个 JavaScript 函数,返回大写化的值。Vue.js 提供数个内置过滤器。管道语法不是JS语法,不能在表达式内使用过滤器,只能添加到表达式的后面。
过滤器可以串联:
{{message | filterA|filterB }}
过滤器也可以接受参数:
{{ message | filterA 'arg1' arg2 }}
过滤器函数始终以表达式的值作为第一个参数。带引号的参数视为字符串,而不带引号的参数按表达式计算。这里,字符串
'arg1'
将传给过滤器作为第二个参数,表达式
arg2
的值在计算出来之后作为第三个参数。
指令:
指令 (Directives) 是特殊的带有前缀 v-
的特性。指令的值限定为绑定表达式,因此上面提到的 JavaScript 表达式及过滤器规则在这里也适用。指令的职责就是当其表达式的值改变时把某些特殊的行为应用到 DOM 上。
<p v-if="greeting">Hello!</p>
这里
v-if
指令将根据表达式
greeting
值的真假删除/插入
<p>
元素。
参数:有些指令可以在其名称后面带一个“参数” (Argument),中间放一个冒号隔开。例如,v-bind
指令用于响应地更新 HTML 特性:
<a v-bind:href="url"></a>
这里 href
是参数,它告诉 v-bind
指令将元素的 href
特性跟表达式 url
的值绑定。
v-bind:可以简写为 :
另一个例子是 v-on
指令,它用于监听 DOM 事件:
<a v-on:click="doSomething">
这里的参数是被监听的事件的名字。v-on:可以简写为 @
v-bind 和 v-on 的缩写是完全合理的,在Vue.js支持的浏览器中均能够被正确的解析,这也是两个最常用的指令!
修饰符:
修饰符 (Modifiers) 是以半角句号 .
开始的特殊后缀,用于表示指令应当以特殊方式绑定。例如 .literal
修饰符告诉指令将它的值解析为一个字面字符串而不是一个表达式。
计算属性
模板是为了描述视图的结构。在模板中放入太多的逻辑会让模板过重且难以维护。这就是为什么 Vue.js 将绑定表达式限制为一个表达式。如果需要多于一个表达式的逻辑,应当使用计算属性。
计算属性: vs.$watch
Vue.js 提供了一个方法 $watch
,它用于观察 Vue 实例上的数据变动。不过,通常更好的办法是使用计算属性而不是一个命令式的 $watch
回调。
<div id="demo">{{fullName}}</div>
var vm = new Vue({
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
} } })