# Vue 快速入门
# Vue.js介绍
Vue.js (opens new window) 是当下很火的一个 JavaScript MVVM 库,它是以数据驱动和组件化的思想构建的。相比于 Angular.js,Vue.js 提供了更加简洁、更易于理解的 API,使得我们能够快速地上手并使用 Vue.js。
如果你之前已经习惯了用 jQuery 操作 DOM,学习 Vue.js 时请先抛开手动操作 DOM 的思维,因为 Vue.js 是数据驱动的,你无需手动操作 DOM。它通过一些特殊的 HTML 语法,将 DOM 和数据绑定起来。一旦你创建了绑定,DOM 将和数据保持同步,每当变更了数据,DOM 也会相应地更新。
当然了,在使用 Vue.js 时,你也可以结合其他库一起使用,比如 jQuery。
# MVVM模式
下图不仅概括了 MVVM 模式( Model-View-ViewModel ),还描述了在 Vue.js 中 ViewModel 是如何和 View 以及 Model 进行交互的。
ViewModel 是 Vue.js 的核心,它是一个 Vue 实例。 Vue 实例是作用于某一个 HTML 元素上的,这个元素可以是 HTML 的 body 元素,也可以是指定了 id 的某个元素。
当创建了 ViewModel 后,双向绑定是如何达成的呢?
首先,我们将上图中的DOM Listeners
和Data Bindings
看作两个工具,它们是实现双向绑定的关键。
从 View 侧看,ViewModel
中的DOM Listeners
工具会帮我们监测页面上 DOM 元素的变化,如果有变化,则更改 Model 中的数据;
从 Model 侧看,当我们更新 Model 中的数据时,Data Bindings 工具会帮我们更新页面中的 DOM 元素。
# Hello World示例
了解一门语言,或者学习一门新技术,编写 Hello World
示例是我们的必经之路(需要通过 CDN 方式去使用 Vue 的,可以下载 Vue 的资源到本地,引入资源即可。
这段代码在画面上输出Hello World!
。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!--这是我们的View-->
<div id="app">
{{ message }}
</div>
</body>
<script src="js/vue.js"></script>
<script> // 这是我们的Model
var exampleData = {
message: 'Hello World!'
}
// 创建一个 Vue 实例或 "ViewModel"
// 它连接 View 与 Model
new Vue({
el: '#app',
data: exampleData
}) </script>
</html>
使用 Vue 的过程就是定义 MVVM 各个组成部分的过程的过程。
- 定义 View
- 定义 Model
- 创建一个 Vue 实例或 "ViewModel",它用于连接 View 和 Model
在创建 Vue 实例时,需要传入一个选项对象,选项对象可以包含数据、挂载元素、方法、模生命周期钩子等等。
在这个示例中,选项对象的 el
属性指向View,el: '#app'
表示该Vue实例将挂载到<div id="app">...</div>
这个元素;data属性指向Model,data: exampleData
表示我们的 Model 是
exampleData 对象。
Vue.js 有多种数据绑定的语法,最基础的形式是文本插值,使用一对大括号语法,在运行时双大括号内的message
会被数据对象的 message
属性替换,所以页面上会输出Hello World!
。
双向绑定示例
MVVM 模式本身是实现了双向绑定的,在 Vue.js 中可以使用v-model
指令在表单元素上创建双向数据绑定。
<!--这是我们的View-->
<div id="app">
<p>{{ message }}</p>
<input type="text" v-model="message"/>
</div>
将message
绑定到文本框,当更改文本框的值时,<p>
标签中双大括号内的message
也会被更新。
反过来,如果改变message
的值,文本框的值也会被更新,我们可以在 Chrome 控制台进行尝试。
Vue 实例的data
属性指向exampleData
,它是一个引用类型,改变了exampleData
对象的属性,同时也会影响Vue实例的data
属性。
# Vue.js 的常用指令
上面用到的v-model
是 Vue.js 常用的一个指令,那么指令是什么呢?
Vue.js 的指令是以 v- 开头的,它们作用于 HTML 元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的 HTML 特性( attribute )。
Vue.js 提供了一些常用的内置指令,接下来我们将介绍以下几个内置指令:
- v-if 指令
- v-show 指令
- v-else 指令
- v-for 指令
- v-bind 指令
- v-on 指令
Vue.js 具有良好的扩展性,我们也可以开发一些自定义的指令,后面的文章会介绍自定义指令。
# v-if 指令
v-if
是条件渲染指令,它根据表达式的真假来删除和插入元素,它的基本语法如下:
v-if="_expression_"
expression 是一个返回 bool 值的表达式,表达式可以是一个 bool 属性,也可以是一个返回 bool 的运算式。例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h1>Hello, Vue.js!</h1>
<h1 v-if="yes">Yes!</h1>
<h1 v-if="no">No!</h1>
<h1 v-if="age >= 25">Age: {{ age }}</h1>
<h1 v-if="name.indexOf('jack') >= 0">Name: {{ name }}</h1>
</div>
</body>
<script src="js/vue.js"></script>
<script> var vm = new Vue({
el: '#app',
data: {
yes: true,
no: false,
age: 28,
name: 'keepfool'
}
}) </script>
</html>
注意: yes
, no
, age
, name
这 4 个变量都来源于 Vue 实例选项对象的data
属性。
这段代码使用了 4 个表达式:
- 数据的
yes
属性为true
,所以Yes!
会被输出; - 数据的
no
属性为false,所以No!
不会被输出; - 运算式
age >= 25
返回true
,所以Age: 28
会被输出; - 运算式
name.indexOf('jack') >= 0
返回false
,所以Name: keepfool
不会被输出。
注意:v-if
指令是根据条件表达式的值来执行元素的插入或者删除行为。
这一点可以从渲染的HTML源代码看出来,面上只渲染了3
个<h1>
元素,v-if
值为false的<h1>
元素没有渲染到 HTML。
为了再次验证这一点,可以在 Chrome 控制台更改age
属性,使得表达式age >= 25
的值为false
,可以看到<h1>Age: 28</h1>
元素被删除了。
age
是定义在选项对象的data
属性中的,为什么 Vue 实例可以直接访问它呢?
这是因为每个 Vue 实例都会代理其选项对象里的data
属性。
# v-show指令
v-show
也是条件渲染指令,和v-if
指令不同的是,使用v-show
指令的元素始终会被渲染到 HTML,它只是简单地为元素设置 CSS 的style
属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h1>Hello, Vue.js!</h1>
<h1 v-show="yes">Yes!</h1>
<h1 v-show="no">No!</h1>
<h1 v-show="age >= 25">Age: {{ age }}</h1>
<h1 v-show="name.indexOf('jack') >= 0">Name: {{ name }}</h1>
</div>
</body>
<script src="js/vue.js"></script>
<script> var vm = new Vue({
el: '#app',
data: {
yes: true,
no: false,
age: 28,
name: 'keepfool'
}
}) </script>
</html>
在 Chrome 控制台更改age
属性,使得表达式age >= 25
的值为false
,可以看到<h1>Age: 24</h1>
元素被设置了style="display:none"
样式。
# v-else指令
可以用v-else
指令为v-if
或v-show
添加一个“else块”。v-else
元素必须立即跟在v-if
或v-show
元素的后面——否则它不能被识别。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<h1 v-if="age >= 25">Age: {{ age }}</h1>
<h1 v-else>Name: {{ name }}</h1>
<h1>---------------------分割线---------------------</h1>
<h1 v-show="name.indexOf('keep') >= 0">Name: {{ name }}</h1>
<h1 v-else>Sex: {{ sex }}</h1>
</div>
</body>
<script src="js/vue.js"></script>
<script> var vm = new Vue({
el: '#app',
data: {
age: 28,
name: 'keepfool',
sex: 'Male'
}
}) </script>
</html>
v-else
元素是否渲染在HTML中,取决于前面使用的是v-if
还是v-show
指令。
这段代码中v-if
为true
,后面的v-else
不会渲染到 HTML;v-show
为true
,但是后面的v-else
仍然渲染到 HTML 了。
# v-for指令
v-for
指令基于一个数组渲染一个列表,它和 JavaScript 的遍历语法相似:
v-for="item in items"
items
是一个数组,item
是当前被遍历的数组元素。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="styles/demo.css" />
</head>
<body>
<div id="app">
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Sex</th>
</tr>
</thead>
<tbody>
<tr v-for="person in people">
<td>{{ person.name }}</td>
<td>{{ person.age }}</td>
<td>{{ person.sex }}</td>
</tr>
</tbody>
</table>
</div>
</body>
<script src="js/vue.js"></script>
<script> var vm = new Vue({
el: '#app',
data: {
people: [{
name: 'Jack',
age: 30,
sex: 'Male'
}, {
name: 'Bill',
age: 26,
sex: 'Male'
}, {
name: 'Tracy',
age: 22,
sex: 'Female'
}, {
name: 'Chris',
age: 36,
sex: 'Male'
}]
}
}) </script>
</html>
我们在选项对象的data
属性中定义了一个people
数组,然后在#app
元素内使用v-for
遍历people
数组,输出每个person
对象的姓名、年龄和性别。
# v-bind指令
v-bind
指令可以在其名称后面带一个参数,中间放一个冒号隔开,这个参数通常是 HTML 元素的特性( attribute ),例如:v-bind:class
v-bind:_argument_="_expression_"
下面这段代码构建了一个简单的分页条,v-bind
指令作用于元素的class
特性上。
这个指令包含一个表达式,表达式的含义是:高亮当前页。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="styles/demo.css" />
</head>
<body>
<div id="app">
<ul class="pagination">
<li v-for="n in pageCount">
<a href="javascripit:void(0)" v-bind:class="activeNumber === n + 1 ? 'active' : ''">{{ n + 1 }}</a>
</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script> var vm = new Vue({
el: '#app',
data: {
activeNumber: 1,
pageCount: 10
}
}) </script>
</html>
注意v-for="n in pageCount"
这行代码,pageCount
是一个整数,遍历时n
从0
开始,然后遍历到pageCount – 1
结束。
# v-on指令
v-on
指令用于给监听 DOM 事件,它的用语法和v-bind
是类似的,例如监听<a>
元素的点击事件:
<a v-on:click="doSomething">
有两种形式调用方法:
绑定一个方法(让事件指向方法的引用),或者使用内联语句。 Greet
按钮将它的单击事件直接绑定到greet()
方法,而Hi
按钮则是调用say()
方法。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<p><input type="text" v-model="message"></p>
<p>
<!--click事件直接绑定一个方法-->
<button v-on:click="greet">Greet</button>
</p>
<p>
<!--click事件使用内联语句-->
<button v-on:click="say('Hi')">Hi</button>
</p>
</div>
</body>
<script src="js/vue.js"></script>
<script> var vm = new Vue({
el: '#app',
data: {
message: 'Hello, Vue.js!'
},
// 在 `methods` 对象中定义方法
methods: {
greet: function() {
// // 方法内 `this` 指向 vm
alert(this.message)
},
say: function(msg) {
alert(msg)
}
}
}) </script>
</html>
# v-bind 和 v-on 的缩写
Vue.js 为最常用的两个指令v-bind
和v-on
提供了缩写方式。v-bind
指令可以缩写为一个冒号:
,v-on
指令可以缩写为@
符号。
<!--完整语法-->
<a href="javascripit:void(0)" v-bind:class="activeNumber === n + 1 ? 'active' : ''">{{ n + 1 }}</a>
<!--缩写语法-->
<a href="javascripit:void(0)" :class="activeNumber=== n + 1 ? 'active' : ''">{{ n + 1 }}</a>
<!--完整语法-->
<button v-on:click="greet">Greet</button>
<!--缩写语法-->
<button @click="greet">Greet</button>