Vue
的生命周期是很重要的一个部分,理解这部分内容有利于我们更加了解vue
的工作原理,这篇文章就来记录一下vue
的生命周期(选项式API
)
注意:
vue2
和vue3
的生命周期是有区别的,这里只给出了选项式API
中最重要的 8 个生命周期钩子函数
📝 vue
官网对生命周期的描述
每个 Vue
实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM
并在数据变化时更新 DOM
等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
总结一下,就是在vue
从创建实例到最终销毁的过程中,会经历不同的阶段,在每个阶段时会执行不同的函数,这些函数就叫做 —— 生命周期钩子函数
# beforeCreate
在我们创建一个vue
实例之后,首先要执行的就是初始化的工作,那就要搞明白初始化了哪些东西
第一次初始化,实例有了事件,比如.once, .trim
这些事件修饰符,有了生命周期函数
何处调用?
会在实例初始化完成、props
解析之后、data()
和 computed
等选项处理之前立即调用。
组合式API
中的setup()
钩子会在所有选项式API
钩子之前调用,beforeCreate()
也是这样
# created
第二次初始化,此时在vue
实例上可以看到_data
,同时实例对象上可以看到对应的代理属性,计算属性,方法和侦听器
何处调用?
在组件实例处理完所有与状态相关的选项后调用。
# 编译模板阶段
在初始化之后,会检查有没有配置el
,也就是vue
实例应该挂载到哪个位置(要服务的容器),比如el : root
,那就会去找id
为root
的元素,
此时需要判断有没有配置el
- 如果没有,就会进入等待,直到
vm.$mount
(要服务的容器)执行,如果不执行该语句,那就永远不会进行到后边的阶段 - 如果有,那就进行下一步检查
直到要服务的容器找到后,开始检查是否配置了template
- 如果有,直接编译
template
中的内容作为模板(注意要写成单根组件),进行渲染 - 如果没有,就把
el
(要服务的容器)外部的html
中的模板编译为模板 —— 也就是div id = "root"
中的所有内容
这个过程 vue 开始了编译模板的工作,生成虚拟DOM
(内存中),所以页面中会显示html
渲染后的结果,但不会显示解析好的内容
# beforeMount
在编译完模板之后,马上要进行的是挂载工作
在挂载之前,此时呈现的是未经过 Vue 编译的 DOM,你可以对 DOM 进行操作,但这些操作最终都不会有效果,(如果你停在这个钩子函数这里,可以看到效果,但是在整个过程中,你修改的 DOM 都会在转换成真实 DOM 后被替换,所以在这里操作 DOM 是没有意义的)
此时组件已经完成了其响应式状态的设置,但还没有创建 DOM
节点,它即将首次执行 DOM
渲染过程。
何处调用?
在挂载开始之前被调用
# mounted
此时页面呈现的是经过Vue
编译的DOM
,此时可以操作DOM
了(但是不建议),至此页面的整个初始化过程结束
所以一般会在这个钩子函数中开启定时器,发送网络请求,订阅消息,绑定自定义事件等初始化操作
何处调用?
挂载之后调用,并且这时 el
被新创建的 vm.$el
替换了
mounted
不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted
内部使用 vm.$nextTick
:
mounted: function () {
this.$nextTick(function () {
// 仅在整个视图都被渲染之后才会运行的代码
})
}
# beforeUpdate
何处调用?
在组件即将因为一个响应式状态变更而更新其 DOM
树之前调用。
在这个钩子函数中适合在现有 DOM
将要被更新之前访问它,比如移除手动添加的事件监听器。
也可以用来在 Vue
更新 DOM
之前访问 DOM
状态。在这个钩子中更改状态也是安全的。
# updated
父组件的更新钩子将在其子组件的更新钩子之后调用。
这个钩子会在组件的任意 DOM
更新后(随便哪个更新)被调用,这些更新可能是由不同的状态变更导致的。如果你需要在某个特定的状态更改后访问更新后的 DOM
,请使用 nextTick()
作为替代。
不要在updated
钩子中修改组件的状态,可能会导致无限循环
何处调用?
在组件因为一个响应式状态变更而更新其 DOM
树之后调用。
updated
也不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 updated
里使用 vm.$nextTick
mounted: function () {
this.$nextTick(function () {
// 仅在整个视图都被渲染之后才会运行的代码
})
}
# beforeDestroy
在该钩子函数中,实例仍然完全可用,可以访问数据和方法,但所有对数据的修改就没用了,但是此时操作实例也是没有意义的,因为实例马上就要销毁了
在这个钩子函数中一般会执行关闭定时器,取消订阅消息,解绑自定义事件等收尾操作
何处调用?
实例销毁之前调用
# destroyed
该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
销毁后通过Vue dev tool
看不到任何信息
原生的DOM
事件只要绑定了就去除不掉了,vue
实例销毁了之后,原生的DOM
事件仍然是可以调用的,比如button
的click
事件
何处调用?
实例销毁后调用
# 总结
常用的生命周期钩子
mounted
: 发送ajax
请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。beforeDestroy
: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。