上一章我们已经使用 Vue.js 实现了简单的功能。现在再回过头来看看我们所写的代码究竟代表了什么。让我们回到第一个例子:
<!DOCTYPE html> <html> <head> <title>Brief Vue.js</title> </head> <body> <h1>{{ message }}</h1> <script src="http://cdn.bootcss.com/vue/1.0.22/vue.js"></script> <script> Vue.config.debug = true; new Vue({ el: 'body', data: { message: 'Hello, world!' } }); </script> </body> </html>
前面已经提到,使用 jQuery 手工操作 DOM 时,我们需要告诉页面,应该如何组织各个组件,这样的代码是命令式的,通常会有很大的重复。Vue.js 的核心则是一个数据绑定系统,允许数据与 DOM 保持同步。Vue.js 使用数据驱动视图的概念。类似于 Flex,可以让我们在普通的 HTML 模板中使用特殊的语法,将 DOM “绑定”到底层数据。这就是 MVVM 模型:一旦创建了绑定,DOM 将与数据保持同步;每当修改了数据,DOM 会自动更新。如此一来,应用中的逻辑几乎都是针对底层数据进行操作,不必关心 DOM 如何更新。
每个Vue
对象都会代理其data
属性。其含义是,我们可以直接通过Vue
对象存取原本定义在data
中的数据。考虑下面的代码:
var vm = new Vue({ data: { message: 'Hello, world!' } });
我们既可以使用data.message
访问到message
数据,也可以使用vm.message
访问。事实上,更多时候,我们都会使用后面的方式:
vm.message === data.message // -> true // 设置属性也会影响到原始数据 vm.message = 2 data.message // -> 2 // ... 反之亦然 data.message = 3 vm.message // -> 3
值得注意的是,只有这些被代理的属性是可响应的,也就是支持双向数据绑定。由于 JavaScript 是动态类型的,我们可以随时添加新的属性,这些在运行时动态添加的属性是不能够触发视图的自动更新的。
Vue
实例在创建时有一系列的初始化步骤,同时提供了一系列回调函数,用于在不同生命周期运行自定义逻辑。例如,有时我们希望在组件准备完毕时执行另外一些操作,那么就可以使用ready
回调函数:
var vm = new Vue({ data: { a: 1 }, ready: function () { // this 指向 vm 实例 console.log('a is: ' + this.a) } }) // -> "a is: 1"
这其中,左侧红色方框里面的就是 Vue.js 提供的回调函数名称。
Vue.js 最强大的双向数据绑定是使用{{}}
语法的。前面我们已经见识过双向数据绑定的使用方法。另外,如果想要进行单次插值,也就是数据以后的变化都不再进行视图的更新,则可以使用下面的语法:
<span>This will never change: {{* msg }}</span>
{{}}
语法会将数据解释为纯文本,如果你想输出 HTML,则必须使用{{{}}}
语法。但是,此时其中的数据绑定就会被忽略。基于安全的考虑,除非是值得信任的代码,否则永远不应该直接输出 HTML。
除了上面见到的简单的属性绑定,{{}}
还支持绑定 JavaScript 表达式。例如:
{{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }}
在上一章最后的几个例子,我们还看到了 Vue.js 的指令。指令是带有前缀v-
的特殊语句,其值限定为绑定表达式,作用是当表达式的值改变时,把某些特殊的行为应用到对应的 DOM 上。例如上一章最后的例子:
<ul v-for="aItem in items"> <li>{{ aItem }} <button @click="remove($index)">X</button></li> </ul>
v-for
就是一个指令。当其绑定的items
属性发生变化时,会自动遍历items
属性的元素,并由此新增一个<li>
标签。Vue.js 提供了很多指令,用于完成不同的功能。这些指令包括:
- v-text
- v-html
- v-if
- v-show
- v-else
- v-for
- v-on(简写作 @)
- v-bind(简写作 :)
- v-model
- v-ref
- v-el
- v-pre
- v-cloak
我们会在后面的章节见到这些指令。
有些指令需要参数,此时,参数与指令之间使用“:”分割。例如,v-bind
指令用于将数据绑定到 DOM 属性。例如,我们需要将属性url
绑定到<a>
的href
属性。那么,我们就可以这么写:
<a v-bind:href="url"></a>
这里的href
是指令v-bind
的参数,告诉v-bind
指令将元素的href
与表达式url
的值进行绑定。当然,我们也可以直接这么写:
<a href="{{url}}"></a>
二者是等价的。事实上,{{}}
就是将数据转换为v-bind
的绑定实现的。
另外一个例子是我们见过的事件处理函数:
<input type="text" v-model="item" @keyup.enter="add" />
这个语句等价于:
<input type="text" v-model="item" v-on:keyup.enter="add" />
@
就是v-on
指令的简写,仅此而已。因此,我们前面的语句又可以写作:
<a :href="url"></a>
与单纯的v-bind
指令不同。除了参数click
,v-on
指令还有额外的修饰符.enter
。修饰符以半角句号 . 开始,是指令的一种特殊后缀,用于表示指令应当以特殊方式绑定。例如.enter
修饰符告诉指令,click
事件只关心回车键,其余按键事件都不关心。我们可以在 Vue.js 的文档找到有关修饰符的说明。