Vue生命周期详述
每次面试都会被问到vue是否熟悉,回答得都不够具体,其实vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
详解生命周期——图解
Vue 1.0+ | Vue 2.0+ | 描述 |
---|---|---|
init | beforeCreate | 组件实例刚被创建,组件属性计算之前,如data等 |
created | created | 组件实例创建完成,属性已绑定,但DOM还没生成,$el还不存在 |
beforeCompile | beforeMount | 模板编译/挂载之前 |
compiled | mounted | 模板编译/挂载之后 |
ready | mounted | 模板编译/挂载之后(不保证组件已在document中) |
- | beforeUpdate | 组件更新之前 |
- | updated | 组件更新之后 |
- | activated | for keep-alive,组件被激活时调用 |
- | deactivated | for keep-alive,组件被移除时调用 |
attached | - | (废弃) 附属时调用 |
detached | - | (废弃) 分离时调用 |
beforeDestory | beforeDestory | 组件销毁之前调用 |
destoryed | destoryed | 组件销毁后调用 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue入门之 生命周期详解</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
</div>
<script type="text/javascript">
console.log("--------------第一阶段-----创建和挂载---------------------");
var app=new Vue({
el:'#app',
data:{
message:'hello world!'
},
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","message: " + this.message) //undefined
},
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","message: " + this.message); //已被初始化
},
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","message: " + this.message); //已被初始化
},
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","message: " + this.message); //已被初始化
},
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.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
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.$data);
console.log("%c%s", "color:red","message: " + 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","message: " + this.message);
},
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","message: " + this.message)
}
});
setTimeout(function(){
console.log("--------------第二阶段-----更新--------------------------");
app.message = "updated message";
},1000);
setTimeout(function(){
console.log("--------------第三阶段-----销毁--------------------------");
app.$destroy();
},2000);
</script>
</body>
</html>
阶段分析
在chrome浏览器里打开,F12看console查看,分三个阶段解读:
阶段一:创建和挂载
- beforecreated:el 和 data 并未初始化
- created:完成了 data 数据的初始化,el没有
- beforeMount:完成了 el 和 data 初始化
- mounted :完成挂载
阶段二:更新
- beforeUpdate:虚拟DOM中根据data变化去更新html
- updated:将虚拟DOM更新完成的HTML更新到页面中
阶段三:销毁
-
beforeDestroy:销毁之前调用
-
destroyed:销毁之后调用,之后再执行app.message= ‘hello vue’,页面不会同步更新。
图解分析
create 和 mounted 相关
另外在created到beforeMount挂载,我们能发现el还是 ,这里就是应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了。到后面mounted挂载的时候再把值渲染进去。
destroy 相关
有关于销毁,暂时还不是很清楚。我们在console里执行下命令对 vue实例进行销毁。销毁完成后,我们再重新改变message的值,vue不再对此动作进行响应了。但是原先生成的dom元素还存在,可以这么理解,执行了destroy操作,后续就不再受vue控制了。
生命周期总结
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化(创建和挂载)、运行中(更新)、销毁。
-
实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作
-
挂载数据,绑定事件等等,然后执行created函数,这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
-
接下来开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数,在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取
-
接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情…
-
当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿
-
当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom
-
当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等
-
组件的数据绑定、监听…去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以