# Vue 文档初探(一): Vue 实例
# 创建实例
let vm = new Vue({ //options });
Copied!
2
3
当一个 Vue 实例创建后, 它的options
都会添加到reactivity system
里. 当options
的属性变化后, 视图(view)就会响应(react), 然后更新.
<template> <div id="app">Vue {{a}}</div> </template> <script> let data = { a: 1 }; console.log(data); export default { data() { return data; } }; </script>
Copied!
2
3
4
5
6
7
8
9
10
11
12
无论从实例上修改还是在data
属性里修改, Vue 都会进行响应并对数据进行更新, 但是对于没有被添加到reactivity system
里的属性是不会响应更新的, 比如给实例vm
添加属性b
, data
是读不到b
属性的.这是由于 Vue 使用了Object.defineProperty()
进行监听的, 它只对调用的对象已有的属性进行监听, 无法监听到新增属性.
# 不要跟踪变化
如果你不想让你的属性被reactivity system
监听并更新, 可以使用Object.freeze(obj)
.
<div id="app"> <p>{{foo}}</p> <button @click="foo = 'baz'">change</button> //Error in v-on handler: "TypeError: //Cannot assign to read only property 'foo' of object '#<Object>'" </div>
Copied!
2
3
4
5
6
let obj = { foo: "bar" }; Object.freeze(obj); let vm = new Vue({ el: "#app", data: obj });
Copied!
2
3
4
5
6
7
8
# 暴露出的属性
Vue 会暴露出实例的属性让我们在外部也可以使用 Vue 提供的属性和方法.为了和用户自定义的属性相区别, Vue 实例的属性都会在首字符加一个$
.
let data = { a: 1 }; let vm = new Vue({ el: "#app", data: data }); console.log(vm.$data === data); //true console.log(vm.$el === document.querySelector("#app")); //true vm.$watch("a", (newValue, oldValue) => { console.log(newValue); console.log(oldValue); });
Copied!
2
3
4
5
6
7
8
9
10
11
12
13
<div id="app"> {{a}} <button @click="a+=1">+1</button> // 2 1 </div>
Copied!
2
3
4
# 生命周期钩子
当我们创建一个 Vue 实例时, 每一个实例都会经历一系列的初始化步骤. 比如设置数据观察, 模板编译, 挂载实例到 DOM 上, 随着数据更新而更新 DOM. 在这一系列过程里还会运行一些叫生命周期钩子(lifecycle hooks)
的函数, 它使得用户可以添加自己的代码到具体的每个阶段. 常用的钩子有created
, mounted
, updated
, destroyed
.
new Vue({ data: { a: 1 }, created: function() { // `this` points to the vm instance console.log("a is: " + this.a); } }); // => "a is: 1"
Copied!
2
3
4
5
6
7
8
9
10
在使用钩子函数时, 最好不要使用箭头函数. 钩子函数里的this
指向调用它的实例.
# 指令
Vue 内置了指令给我们使用, 指令都是以v-
作为前缀的.它是许多功能的一个集合.如v-if
, v-bind
, v-on
.Vue 还提供用户自定义指令的功能, 实在强大.
<p v-if="seen">Now you see me</p>
上面这个代码使用了v-if
指令, 它将根据实例里data
的seen
的真值来判断是否显示这个p
标签.
# 参数
指令也可以带上参数, 见下面的代码:
<a v-on:click="doSomething"> ... </a>
click
就是指令的参数. 它监听click
事件, 然后触发doSomething
.
# 动态参数
上面我们将参数写死了, 动态参数可以在data
里写我们的属性, 在不造成 bug 的情况下可以任意修改, 增加了灵活性.
let vm = new Vue({ el: "#app", template: `<div> <p>hello</p> <a :[attributeName]="url">link</a> </div>`, data: { attributeName: "href", url: "https://baidu.com" } });
Copied!
2
3
4
5
6
7
8
9
10
11
# 修饰符
修饰符写在指令的最后面, 表示指令要以某种方式绑定.比如, 我们绑定一个form
表单提交的事件, 并且阻止默认行为.
<form v-on:submit.prevent="onSubmit"> ... </form>
.prevent
就是一个修饰符, 它由 Vue 提供.
# sync
修饰符
我们会遇到这样一个场景: 父组件的 data 通过prop
传入子组件里, 子组件会在某件事发生后要修改prop
的值. 在这个场景里, 如果直接修改prop
会得到一个报错信息.
// Father new Vue({ data() { return { n: 1 }; }, template: ` <Son :count="n"> ` }); // Son new Vue({ props: ["count"], template: ` <p>{{count}}</p> <button @click="count+=1">+1</button> // 报错!! ` });
Copied!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
有两种办法可以解决:
# 传递 message 到父组件, 在父组件更改
// Father new Vue({ data() { return { n: 1 }; }, template: ` <Son :count="n" @increment="handleIncrement"> `, methods: { handleIncrement() { this.n += 1; } } }); // Son new Vue({ props: ["count"], template: ` <p>{{count}}</p> <button @click="$emit('increment')">+1</button> ` });
Copied!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 使用.sync
修饰符
// Father new Vue({ data() { return { n: 1 }; }, template: ` <Son :count="n" @update:increment="n = $event">// $event的值就是在子组件$emit()的第二个参数 ` }); // Son new Vue({ props: ["count"], template: ` <p>{{count}}</p> <button @click="$emit('update:increment', count+1)">+1</button> ` });
Copied!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
由于上面的代码范式很常用或是很重要, Vue 把它封装进内置的修饰符里了, 取名叫sync
.
// Father <Son :count.sync="n"> // Son $emit('update:count', val) //发射信息是约定好的, 不要修改
Copied!
2
3
4
5
# data
既是对象又是函数
在 Vue 里面, data
这个选项有时写成对象, 有时写成函数. 它们是有区别的.
// object syntax data: { // options } // function syntax data: function(){ return { // options } }
Copied!
2
3
4
5
6
7
8
9
10
11
在非组件里使用对象语法是完全没有问题的, 而一旦在组件里并且考虑复用组件时则必须使用函数语法. 因为考虑到组件的复用, 我们希望每个组件的状态是各自独立的. 使用 object syntax 会使复用组件使用同一个data
对象. 所以我们使用 function syntax 使得每次实例化组件然后调用data
函数时都返回一个新的对象.