# Vue2教程 - 12 生命周期函数
生命周期函数也就是组件从创建到销毁的过程中,触发的回调方法,我们可以在回调方法中进行一些操作。
通过学习组件的生命周期函数,我们可以知道在哪个生命周期函数中可以发起网络请求来获取数据,在哪个生命周期函数中才可以获取到组件中的数据,哪个生命周期函数中可以操作DOM。
# 12.1 生命周期
下图展示了Vue对象实例的生命周期。(来自官网)
下面解释一下:
# 1 new Vue()
表示开始创建一个Vue的实例对象;
# 2 初始化事件&生命周期函数
表示刚初始化了一个Vue空的实例对象,这个时候这个对象上只有默认的一些默认的事件和生命周期函数,其他的东西都未创建。
注意:在 beforeCreate
生命周期函数执行的时候,data
和 methods
中的数据都还没有被初始化。
<!-- 在使用独立安装方式使用vue.js,使用过这样的方式 -->
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() { // 这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
// console.log(this.msg)
// this.show()
// 注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3 初始化注入&校验
在这一步会初始化 Vue 对象中的 data
和 methods
等属性,所以在后面的 created
生命周期函数中,data
和 methods
已经被初始化好了。
所以如果想调用 methods
中的方法或操作 data
中的数据,最早只能在 created
函数中操作。
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() {},
created() { // 这是遇到的第二个生命周期函数
// console.log(this.msg)
// this.show()
// 在 created中,data 和 methods 都已经被初始化好了!
// 如果要调用methods中的方法,或者操作data中的数据,最早只能在created中操作
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 4 是否指定el选项
查看Vue对象是否有el属性。
# 5 是否指定templete选项
查看Vue对象是否有template属性
# 6 将template编译到render函数中
# 7 将el“内”部的HTML作为template编译
将el指定的元素内部的html作为模板进行编译。
上面的四步主要是进行模板编译,将Vue代码中的那些指令进行执行,最终在内存中生成一个编译好的最终模板字符串,然后把这个模板字符串渲染为内存中的DOM,此时只是在内存中渲染好了模板,并没有把模板挂载到真正的页面中去。
接下来回执行 beforeMount
生命周期函数,这个时候页面模板已经加载到内存中了,尚未挂载到页面中,页面中的元素还是模板字符串,不是真正显示的内容。
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{msg}}</h3>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() {},
created() {},
beforeMount() { // 这是遇到的第3个生命周期函数,表示模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中
console.log(document.getElementById('h3').innerText); //打印内容:{{msg}}
// 在beforeMount执行的时候,页面中的元素还没有被真正替换过来,只是之前写的一些模板字符串
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 8 创建vm.$el并用其替换el
这一步将内存中编译好的模板正式替换到浏览器页面中去,然后会执行 mounted
生命周期函数。
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{ msg }}</h3>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() {},
created() {},
beforeMount() {},
mounted() { // 这是遇到的第4个生命周期函数,表示内存中的模板已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
console.log(document.getElementById('h3').innerText); //打印内容:ok
// 注意: mounted 是实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,此时,如果没有其它操作的话,这个实例就静静的躺在我们的内存中,一动不动
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
如果想要通过某些插件操作页面上的DOM节点,最早要在 mounted
中进行。
只要执行了 mounted
,就表示整个Vue实例已经初始化完成了,此时组件已经脱离了创建阶段,进入到了运行阶段。
# 9 挂载完毕
此时组件已经被挂载到页面。
当每次data被修改时,都会调用 beforeUpdate
生命周期方法,这时data中的数据已经更新了,但是界面还没有渲染。
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{msg}}</h3>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
// 接下来的是运行中的两个事件
beforeUpdate() { // 这时候,表示我们的界面还没有被更新,数据已经被更新了
//当点击修改msg按钮时,data数据被修改了,回调了beforeUpdate生命周期方法
console.log('界面上元素的内容:' + document.getElementById('h3').innerText);
console.log('data中的msg数据是:' + this.msg)
// 得出结论:当执行beforeUpdate的时候,页面中的显示的数据还是旧的,此时data数据是最新的,页面尚未和最新的数据保持同步
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 10 虚拟DOM重新渲染并应用更新
先根据data中最新的数据,在内存中重新渲染出一份最新的内存DOM树,当最新的内存DOM树被更新之后,会把最新的内存DOM树重新渲染到页面中去,这时候就完成了从 data(Model层)-> view(视图层)
的更新。
页面重新渲染完成,会执行 updated
生命周期函数,这个时候页面和 data
数据已经保持了同步了,都是最新的。
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
msg: 'ok'
},
methods: {
show() {
console.log('执行了show方法')
}
},
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {
console.log('界面上元素的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据是:' + this.msg)
// updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
}
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 11 解除绑定销毁子组件及事件监听
当执行 beforeDestroy
生命周期函数的时候,Vue实例就已经从运行阶段,进入到了销毁阶段;
当执行 beforeDestroy
的时候,实例身上所有的 data
和所有的 methods
以及过滤器、指令都处于可用状态,此时还没有真正执行销毁的过程。
# 12 销毁完毕
当执行到 destroyed
函数的时候,组件已经被完全销毁了,此时组件中所有的数据,方法、过滤器、指令等都已经不可用了。
# 12.2 总结生命周期函数
组件的生命周期可以分为四个阶段:
# 1 创建
- beforeCreate:此时组件的
data
和methods
等属性均不存在,即无法访问到组件的属性和方法。 - created:在实例创建完成后被立即调用。在这一步,可以调用 methods 中的方法和 data 中的数据,但无法访问到DOM元素。发送网络请求从后端服务器获取数据,建议放在这个函数中发起。
# 2 挂载
- beforeMount:在挂载开始之前被调用,此时组件的模板已经编译完成,但尚未挂载到DOM树中,页面还是Vue的占位符。
- mounted:此时组件已经成功地挂载到DOM树中,可以进行DOM操作。
# 3 更新
- beforeUpdate:由于数据更改导致虚拟DOM重新渲染之前调用。
- updated:组件发生更新,重新渲染之后会调用该函数,此时组件 DOM 已经更新,需要注意,要避免在此期间更改数据,因为这可能会导致无限循环。
# 4 销毁
- beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。适合在此进行清理任务,比如清除定时器、解绑全局事件等。
- destroyed:Vue 实例销毁后调用,调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。可用于完成销毁之后的收尾工作。