前言
了解Vue的生命周期很重要!
了解Vue的生命周期很重要!
了解Vue的生命周期很重要!
重要的事情说三遍,至于为什么重要?额…
一、生命周期简介
我们都知道,每一个Vue应用都是从我们通过Vue函数去new一个新的vue实例开始的。每一个vue实例就像我们人一样,都会有从出生走向死亡这样这一过程,这个过程就是我们所说的Vue的生命周期,而这个过程中所经历的各个阶段,就是我们所说的钩子函数,我们必须了解到这个生命周期是一个怎么样的过程,我们才能在每个阶段的钩子函数里去做对的事。
正文开始
首先来个官方的图镇文:
先做个简单的说明:
红色白底方块代表着钩子函数;绿色方法代表着所做的事情;
黄色菱形代表着流程判断;红色圆圈代表着生命周期阶段;
接着再来个Vue生命周期的钩子函数说明图,先做个简单的了解:
二、生命周期详解
对于以上这两个这个图,大家或多或少见过,先做个了解。看不看懂都没关系,我们接下来就来对生命周期做个详细的解析。
首先,简单粗暴地把上面这段代码复制到一个新的html文件,运行它并打开控制台
<!DOCTYPE html>
<html>
<head>
<title>生命周期</title>
<meta charset="UTF-8"/>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p @click="updateMessage">{{ message }}</p>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message : "生命周期"
},
methods:{
updateMessage(){
this.message="message更新了"
}
},
beforeCreate: function () {
console.group('beforeCreate 创建前===============》');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","methods: " + this.updateMessage)
},
created: function () {
console.group('created 创建完成===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","methods: " + this.updateMessage); //已被初始化
},
beforeMount: function () {
console.group('beforeMount 挂载前===============》');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","methods: " + this.updateMessage); //已被初始化
},
mounted: function () {
console.group('mounted 挂载完成===============》');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","methods: " + this.updateMessage); //已被初始化
},
beforeUpdate: function () {
console.group('beforeUpdate 更新前===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.message);
//debugger;
},
updated: function () {
console.group('updated 更新完成===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 销毁前===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","methods: " + this.updateMessage);
},
destroyed: function () {
console.group('destroyed 销毁完成===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","methods: " + this.updateMessage)
}
})
</script>
</body>
</html>
不出意外的话,应该可以看到下图的内容:
上面的运行结果,从上到下就是Vue生命周期的流程。我们就着这个运行结果来逐个解析:
创建阶段:
- 在beforeCreated() 创建前阶段,我们可以看到,el、data、methods都是undefined,也就是说,在这个阶段,其实Vue只是简单地帮我们new出一个实例,但实际上什么事情都没做。
- 在created() 创建完成阶段,我们可以看到,data、methods已经发生了变化,简单地来说,在这个阶段,Vue为我们初始化了data和methods。但注意此时el依然为undefined,所以直到created() 阶段为止,Vue所做的都只是初始化,没做挂载。
挂载(渲染)阶段:
- 我们再来看挂载阶段,先看beforeMount() 挂载前阶段,我们可以看到此时el已经不再undefined了,在这个阶段,可以简单地理解为Vue已经为我们找到了我们要挂载的DOM节点了。但是,大家可以看到,我们绑定的数据是{{message}},还没有渲染出来。
- 接着再来看mounted() 挂载完成阶段,这个时候我们可以看到,我们绑定的数据不再是{{message}}了,而且已经显示出来“生命周期”了,也就是说,在这个阶段,Vue已经帮我们将数据渲染到我们的DOM节点了。至此,前期的创建和渲染阶段已经完成了。
此时,大家可以回过头重新再看vue官方的生命周期流程图,大家可以看到,在创建和挂载阶段中间,多了以下这一块内容,这是为什么呢?
其实原因很简单,说白了,template和el其实都只是一个我们去挂载的模板,也就是容器,只不过el是根节点,template最终也是被塞进el里面的。所以Vue在挂载前会去判断template存不存在,如果存在,那就先挂载到template这个模板里,如果不存在,就直接挂载到el绑定的DOM节点里。
更新阶段
说完了创建和挂载阶段,我们再来看一下更新阶段。首先要记住一点,如果我们的data没有变化,那是不会走进更新阶段的,所以我们点击下页面“生命周期”的文字,修改data,更新下我们的message,来走进更新阶段。
我们可以看到此时已完成了更新,但咋一看beforeUpdate() 更新前和 updated() 更新完成这两个阶段好像没什么区别,但其实是有的。
回到那一大串代码,在beforeUpdat() 里面的所注释掉的//debugger,将他取消注释,我们打个断点,然后重新执行我们的代码,重新点击修改,这时候我们可以看到:
在beforeUpdate() 更新前这个阶段,其实我们的data已经进行了更新,但是我们节点上绑定的数据还没更新,也就是说,在这个阶段,我们只是更新了data,但还没重新渲染DOM。
接着我们继续执行
我们可以看到在updated() 更新完成这个阶段后,我们的data和DOM都已经更新了。
总结一下更新阶段,在beforeUpdate() 阶段,Vue只是帮我们完成了data 的更新,但DOM还没重新渲染。当我们完成updated() 阶段后,我们的DOM才完成重新渲染。
销毁阶段
最后就是销毁阶段了,这个阶段其实没什么好说的,我们可以在控制台执行下app.$destory()这行代码,就可以看到:
在这之后,我们可以看到el,data,methods其实都还存在,但我们去对他们进行操作的话,是不起作用的。我们可以在控制台输入我们的vue实例app,可以看到:
这时的vnode是undefined。简单来说,销毁阶段销毁的是我们的虚拟DOM,以及移除了事件监听和数据绑定。el,data,methods其实都还是存在的,只是与Vue无关了。
如果非要说beforeDestroy() 销毁前阶段和 destroyed() 销毁完成阶段的区别的话,那就是beforeDestroy() 是问Vue确定要销毁吗,而destroyed() 是已经销毁了。
到这里为止,生命周期的详解也解析得差不多了,这里放一张做了注解的官方生命周期图,如果对生命周期还不太清晰的话,可以结合以上内容看看下面这张图,或者觉得了解得差不多了,可以回过头看一开始那张官方的生命周期图,看看现在对这张图有没有变得不再陌生。:
三、生命周期总结
这里是我对各阶段钩子函数做的一个大概的总结。然后也写一下我自己平时会怎么去用这些钩子函数,毕竟学完后不会用也是挺尴尬的。经验有效,写得不全,望大佬补充哈哈哈。
生命周期各阶段 | 钩子函数写法 | 作用 | 其他说明 |
---|---|---|---|
创建前 | beforeCreate() | 在这个阶段什么都没做,这是new一个vue实例而已 | 我们可以在这里加一下loading |
创建完成 | created() | 在这个阶段对data和methdos进行初始化 | 我们可以在这个阶段进行我们的ajax请求,获取数据,或者对某些数据进行初始化 |
挂载前 | beforeMount() | 初始化el,确定挂载节点 | |
挂载完成 | mounted() | 将data和methods等虚拟DOM挂载到DOM | 我们也可以在这个阶段进行ajax请求,拿数据 |
更新前 | beforeUpdate() | data数据修改,但还没更新视图 | 这个阶段如果不进行数据修改,是不会进入的 |
更新完成 | updated() | 将修改好的data数据重新渲染到DOM | |
销毁前 | beforeDestory() | ||
销毁完成 | destory() | 移除事件监听和数据绑定,销毁虚拟DOM | 销毁后的数据还在,只是不再和vue有关联 |
激活时 | activated() | keep-alive组件被激活时调用 | |
停止时 | deactivated() | keep-alive组件停止时调用 |
至于表格里提到的activeted() 和 deactived() 这两个钩子函数,是跟vue的动态组件相关的,表格里只是做了个简单的说明,具体的内容Vue官方文档里写得挺清楚的,这里就不多说了。
最后的最后,这是我第一次写博客,本文仅是自己对Vue生命周期的理解,初来乍到,经验不全,有错误的或者有补充的,望各位大佬指正和补充!!!
参考文献
https://segmentfault.com/a/1190000008010666?utm_source=tag-newest
https://blog.youkuaiyun.com/yy493004893/article/details/78644795