相信大伙学习前端,vue这个框架是大多无法逃避的一个必学点,看了很多也只是理解了vue的几个生命周期是什么意思,但它们具体做了什么或者说起什么样的作用并没有体会到,在这一点上就如vue官网上说的一样,
你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
正如官方文档说的,vue的生命周期会随着你学习的深入越来越清楚。
用官方的话来说就是每一个vue实例从创建到销毁的过程。这个过程,vue经历了创建—初始化数据—编译模板—挂载dom—渲染、更新、渲染、卸载等一系列操作。
先来看看官方给出的一张图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
相信这就是"万恶之源"的开始,让我们来仔细看看这到底是个什么意思
跟字面意思一样,创建一个vue实例,也是每一个vue实例的开始,然后初始化事件(int Events)和初始化生命周期(init Lifecycle)和初始化渲染(init RenderinitRender)
*以下内容对于初学者而言混个眼熟就行
而仅仅是初始化了这三个函数吗,其实也不然,在new vue时,内部会执行一个this._init()方法,这个方法是定义在initMixin中的。vue会去判断当前组件是否存在父组件,如果存在,就会循环的去找第一个非父组件,并将vm push进去作为子元素,定义$parent、$root、$children、$refs
属性及其他属性。
在这个阶段,此阶段还没有开启vue的观察者模式(即vue的双向数据绑定)等等一系列机制,简单点来说就是此阶段的data、methods、props还未被创建好,无法使用。并且会开始初始化init injections(注射)和init reactivity(反应)
ps:在beforecreate这个阶段前会执行一个mergeOptions
函数,得到$options
并且把这个设置成vue实例的属性,这个的作用就是检查我们组件的命名是否合法,是否规范
init injections此方法初始化在data/props之前被调用,作用是初始化vue的inject,也就是以后的传值用的
这个时候vue的data、method已经被初始化,属性也被绑定,但此时还是虚拟dom
,真实dom并没有生成,$el也不能用,这个时候可以调用data和method的数据和方法。此阶段可以获取异步ajax数据
ps:虚拟dom:简单的来说就是一个js对象,用来描述视图的界面结构,每个组件都有一个render函数,每个render函数返回一个虚拟dom树,这个后续会专门写一篇
就如我们上面说的,el在created阶段还是undefined,但数据已经和data的属性进行了绑定。
也就是说会先判断vue实例中有没有el选项,如果没有就停止,知道实例上调用vm.$mount(el) (挂载el),
有的话就进入到判断template模板,如果有template,就把模板编译当成render函数,如果没有就把html当做模板编译,template优先级大于html模板(ps:这里又涉及到vue渲染优先级的问题,简单来说就是render函数>template>html模板,感兴趣的可以查下template)
此时模板已经编译完成,也就是说我们的虚拟dom已经创建完了,但并没有变成真实dom,也就是说并没有真实渲染到页面上,此时el存在,在此阶段更改数据不会触发其他的钩子函数,一般的初始化数据在这里获取
此时模板已经被渲染成真实dom,vue实例中的data里的message挂载到bom节点中去,用户可以看见渲染完成的页面,页面的数据也是通过双向数据绑定显示data中,当mount执行完,也就意味着我们这个vue实例已经完全的创建好了
从mount开始,vue实例有两种走向,一种的是beforeUpdata和destroyed,这里先说beforeUpdata。
更新前状态(view层数据变化前,而不是data数据改变前),重新渲染之前触发,也就是在这个阶段出现了vue非常经典的一个算法diff算法
ps:diff算法,这个比较复杂,感兴趣的可以查查,简单来说就是进行虚拟节点对比,返回一个patch对象,用来存放两个节点的不同地方,最后用patch记录的消息去局部更新dom,节省很多性能
数据已经更新完成,dom也重新render完成
销毁前执行($destroy方法被调用的时候就会执行),一般在这里善后:清除计时器、清除非指令绑定的事件等等…)
销毁后 (Dom元素存在,只是不再受vue控制),卸载watcher,事件监听,子组件
跟vue2相比其实相差不大,区别对比
Vue2生命周期 | Vue3生命周期 |
---|---|
beforeCreate | setup() |
created | setup() |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
vue3在vue2的基础上新增了一个setup方法,
setup 函数是 Vue3 中新增的一个生命周期函数:
setup 函数会在 beforeCreate 之前调用,因为此时组件的 data 和 methods 还没有初始化,因此在 setup 中是不能使用 this 的
所以 Vue 为了避免我们错误的使用,它直接将 setup 函数中的 this 修改成了undefined
setup函数,只能是同步的不能是异步的
加载渲染阶段:父beforeCreate->父Create->父beforeMounte->
子beforeCreate->子Create->子ceforeMounte
挂载:子Mounte->父Mounte
更新:
1.父更新子不更新:父beforeUpdata->父updata
2.子更新父不更新:子beforupdata->子updata
3.父子一起更新:父beforeupdata->子beforeupdata->子updata->父updata
销毁:
父beforeDestroy->子beforeDestroy->子Destroy->父Destroy
这里放一个非常的简单的vue实例来帮大家理解生命周期的全过程
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js">script>
head>
<body>
<div id="app">div>
<script>
new Vue({
data(){
return{
arr:[]
}
},
//一、创建阶段
// 钩子函数,此阶段还没有开启vue的观察者模式(即双向数据绑定)等等一系列机制
// 不能获取dom
beforeCreate() {
console.log('我是创建前的钩子函数')
},
// vue实例创建完成 这个阶段可以做一些准备性的工作 获取异步的数据 ajax
//dom未生成
create(){
console.log('这个阶段,vue的实例已经创建完毕,初始化数据,但是数据并没有显示到页面上 所以不能获取到dom')
this.flage=true;
this.arr=[
{id:1,name:'zhangsan'}
]
},
// 二、挂载阶段
// 挂载前 将template模板 编译成浏览器可读的模式
beforMount(){
console.log('编译阶段,没有挂载上去,不能获取dom')
},
mouted(){
console.log('挂载完成,可以获取dom')
document.addEventListener('click',function(){
})
},
// 三、更新阶段
beforeUpdate() {
console.log('数据更新前')
},
update() {
console.log('数据更新完毕')
},
// 四、销毁阶段
beforeDestroy() {
document.removeEventListener('click')
console.log('准备销毁')
},
destory(){
console.log('已经销毁')
},
})
script>
body>
html>