详细一些的vue生命周期

发布时间 2023-12-06 15:38:01作者: 路泽宇

如果你和我一样,以前对vue生命周期的理解仅限于生命周期钩子,那么本文可以让我们更深入一层,理解vue在生命周期各个阶段所做的事,对我们对vue的理解和使用很有好处。

 

1)通过new Vue()创建新的vue实例

不管页面还是组件,都是一个个vue实例。一个vue应用,其实就是一个个vue实例的嵌套。

2)初始化生命周期和事件监听

vue实例在生命周期中,会用一些内部变量来标志生命周期的当前阶段,比如_isMounted_isDestroyed等,这些标志对于vue的内部运行很重要,决定了在什么时候做什么事。

vue会绑定事件监听函数,包括组件自身的事件监听,和父组件向子组件传递的事件监听。

3beforeCreate钩子

此时还无法访问propsdatacomputedwatchmethods

4)初始化状态

初始化propsdatacomputedwatchmethodsvue会在此时循环遍历propsdatacomputed的每一个属性,用Object.defineProperty()把属性转换为gettersetter,这是vue2实现响应式的基础。

5created钩子

此时propsdatacomputedwatchmethods已经初始化完成,可以通过this来调用了。如果想在进入页面后马上做一些操作,此时是最好的选择,我们一般都在此时调用api拉取数据。

6)开始挂载

如果el属性存在,则执行$mount()开始挂载。否则,等到vm.$mount()被调用时,再开始挂载。

7beforeMount钩子

this.$el开始可以访问,不过此时获取到的是vue实例挂载前的DOM对象。

8)模板编译

检查eltempleterender三个属性,如果render存在,则直接作为render函数进入下一步,否则如果templete存在,则把它编译成render函数,否则如果el存在,则以elouterHTML作为模板编译成render函数。总之,这一步的目的就是得到一个render函数,也就是渲染函数。每一个vue组件都有自己的render函数。

9)生成虚拟DOM

执行render函数,得到虚拟DOM

10)渲染

vue实例的数据填充虚拟DOM,把虚拟DOM(是一个对象)渲染为真实的DOM(就是网页中的DOM元素)。

11)挂载

把真实的DOM挂载到页面中

如果有el属性,则替换掉elouterHTML。如果没有,则会等到$mount()被调用时再挂载(参数可以是css选择器或者DOM对象),同样替换掉目标元素的outerHTML,不管它里面有什么内容。如果没有调用$mount(),则DOM对象会保持在内存中,你可以通过this.$el获取到它,然后手动插入到页面中。

12mounted钩子

此时DOM已经正式挂载到页面中,可以通过this.$el访问到最终的DOM对象。需要访问DOM的操作可以在此时进行,常见于一些第三方库。

13beforeUpdate钩子

当模板的依赖数据发生变化时,beforeUpdate钩子会被触发,模板开始重更新渲染。

14)diffing

生成新的虚拟DOM,和旧的虚拟DOM进行差异化比较,这个过程叫“diffing”。

15)patching

基于上一步的结果,尽可能少的对真实DOM做出修改,这个过程叫“patching”。

16updated钩子

DOM更新完成后,updated钩子被触发,此时,你可以访问到更新后的DOM

我们更常用的是在代码中,修改data数据后想要马上访问到更新后的DOM,此时可以把代码写在this.$nextTick()的参数函数里。

17beforeDestroy钩子

vue实例即将被销毁,但此时实例仍然完全可用。

我们一般在此时做一些清理工作,比如:移除全局的事件监听(比如windowresize事件)、清理setTimeoutsetInterval、释放一些资源(比如websocket连接)、保存组件的状态(比如滚动的位置、复杂的表单输入)。

18destroyed钩子

vue实例已经被销毁,所有的事件监听已经被移除,所有的子实例也已经被销毁。

 

如果该实例有子组件,子组件的从beforeCreatemounted将会插入到该实例的beforeMountmounted之间进行,子组件的beforeDestroydestroyed则会插入到该实例的beforeDestroydestroyed之间进行。至于beforeUpdateupdatedvue组件的更新基于依赖追踪,父组件和子组件的更新没有必然的联系。可以看一下我的上一篇文章:vue的响应式原理:依赖追踪》

有子组件的实例生命周期如下:

1beforeCreate

2created

3beforeMount

4)子组件beforeCreate

5)子组件created

6)子组件beforeMount

7)子组件mounted

8mounted

9beforeDestroy

10)子组件beforeDestroy

11)子组件destroyed

12destroyed

这样的设计,保证了父组件挂载完成时,子组件已全部挂载,父组件销毁时,子组件已全部销毁,确保了它们之间逻辑上的所属关系。

 

本人水平非常有限,写作主要是为了把自己学过的东西捋清楚。如有错误,还请指正,感激不尽。