一、 Vue有几个生命阶段?
vue
一共有 8 个生命阶段,分别是:
- beforCreate
- created
- beforeMount
- Mounted
- beforeUpdate
- Updated
- beforeDesreoy
- Desreoyed
二、了解Vue的生命阶段
定义及作用
- 定义: 每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如需要设置数据监听、编译模板、挂载实例到 DOM、在数据变化时更新 DOM 等,不同的时期对应不同的周期;
- 生命周期钩子: 不同周期开放出来的接口;
- 作用: 可以在特定的时期添加需求,比如请求后台数据等
以下是我对官方图片的一些理解:
当然,如果觉得我理解错误,也希望能评论一下,让我改正。并且,在本文最后,会放上官方原文图片。
三、 Vue的生命周期详解
如果大家还是对vue生命周期还是不太理解的话,那么接着往下看。我将用代码来做一个详细的解析。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue的生命周期</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p>{{msg}}</p>
<button @click="renewal">更新数据</button>
</div>
</body>
<script>
let vm = new Vue({
el: "#app",
data() {
return {
msg: "生命周期",
}
},
methods: {
renewal() {
this.msg = "msg更新了";
}
},
beforeCreate() {
console.group("beforeCreate(开始创建)执行了===============>");
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的renewal: " + this.renewal);
},
created() {
console.group("created((创建完成)执行了===============>");
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的renewal: " + this.renewal);
},
beforeMount() {
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的renewal: " + this.renewal);
},
mounted() {
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的renewal: " + this.renewal);
},
beforeUpdate() {
console.group("beforeUpdate(数据更改前)执行了===============>");
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的renewal: " + this.renewal);
// debugger
},
updated() {
console.group("updated(数据更改完成)执行了===============>");
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的renewal: " + this.renewal);
},
beforeDestroy() {
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的renewal: " + this.renewal);
},
destroyed() {
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的renewal: " + this.renewal);
},
})
</script>
</html>
不出意外的话,应该会显示下面的内容:
这时候,你可以点击更改数据
的按钮,它就会执行 beforeUpdate和updated,并且把p标签的内容改为了msg更新了
.
创建阶段:
- 在beforeCreated() 执行时,我们可以看到,el、data、methods都是undefined,也就是说,在这个阶段,其实Vue只是简单地帮我们new出一个实例,但实际上什么事情都没做。
- 在created() 执行时,我们可以看到,data、methods已经发生了变化,简单地来说,在这个阶段,Vue为我们初始化了data和methods。但注意此时el依然为undefined,所以直到created() 阶段为止,Vue所做的都只是初始化,没做挂载。
挂载(渲染)阶段:
- 在beforeMount() 执行时,我们可以看到此时el已经不再undefined了,在这个阶段,可以简单地理解为Vue已经为我们找到了我们要挂载的DOM节点了。但是,大家可以看到,我们绑定的数据是{{msg}},还没有渲染出来。
- 在mounted() 执行时,这个时候我们可以看到,我们绑定的数据不再是{{msg}}了,而且已经显示出来“生命周期”了,也就是说,在这个阶段,Vue已经帮我们将数据渲染到我们的DOM节点了。至此,前期的创建和渲染阶段已经完成了。
此时,再重新再看vue的生命周期流程图,大家可以看到,在创建和挂载阶段中间,有了以下这一块内容,这是为什么呢?
其实原因很简单,template和el其实都只是一个我们去挂载的模板,也就是容器,只不过el是根节点,template最终也是被塞进el里面的。所以Vue在挂载前会去判断template存不存在,如果存在,那就先挂载到template这个模板里,如果不存在,就直接挂载到el绑定的DOM节点内。
数据更新阶段:
大家可以看到,当我们点击了按钮,就会执行 beforeUpdate 和 updated,如果单看控制台的话,好像是没什么区别的对吧。但其实是有的,因为Vue也不可能创建两个一模一样的钩子函数对吧。
这时候我们可以在beforeUpdat 函数的最后一行写个 debugger
。当然,也可以直接把我放在那里的注释//debugger
放开。然后重新执行我们的代码,重新点击按钮,这时候我们可以看到:
在beforeUpdate() 这个阶段,其实我们的data已经进行了更新,但是我们节点上绑定的数据(msg)还没更新,也就是说,在这个阶段,我们只是更新了data,但还没重新渲染DOM。
接着我们继续执行:
我们可以看到在updated() 更新完成这个阶段后,我们的data和DOM都已经更新了。
总结一下更新阶段,在beforeUpdate() 阶段,Vue只是帮我们完成了data 的更新,但DOM还没重新渲染。当我们完成updated() 阶段后,我们的DOM才完成重新渲染
销毁阶段:
最后就是销毁阶段了,这个阶段其实没什么好说的,我们可以在控制台执行下vm.$destroy()这行代码,就可以看到:
在这之后,我们可以看到el,data,methods其实都还存在,但我们去对他们进行操作的话,是起不来作用的。而我在上面也写到过,这时候的destroyed只剩下一个DOm空壳。我们可以在控制台输入我们的vue实例vm,可以看到:
这时的vnode是undefined。简单来说,销毁阶段销毁的是我们的虚拟DOM,以及移除了事件监听和数据绑定。el,data,methods其实都还是存在的,只是与Vue无关了。
如果非要说beforeDestroy() 执行阶段和 destroyed() 执行阶段的区别的话,那就是beforeDestroy() 是问Vue确定要销毁吗,而destroyed() 是已经销毁了。
到这里为止,Vue的生命周期详解也解析得差不多了。下面我会对Vue的生命周期再做个总结
四、生命周期总结
这里是我对各阶段钩子函数做的一个大概的总结。
生命阶段 | 钩子函数 | 正在进行 |
---|---|---|
开始创建 | beforeCreate | new了一个实例 |
创建完成 | created | 在这个阶段对data和methdos进行初始化 |
挂载前 | beforeMount | 初始化el,确定挂载节点 |
挂载后 | mounted | 将data和methods等虚拟DOM挂载到DOM |
数据更新前 | beforeUpdate | 数据修改了,但还没更新视图 |
数据更新后 | updated | 将修改好的data数据重新渲染到DOM |
销毁前 | beforeDestory | 刚调用了$destroy方法 |
销毁后 | destoryed | 移除事件监听和数据绑定,销毁虚拟DOM |
最后,我在这里放上一张官方的生命周期图,在此希望大家能够理解这张图.