Vue 的生命周期各个阶段
Vue 的生命周期(Lifecycle)是指一个 Vue 组件从创建、挂载、更新到销毁的整个过程。
理解生命周期对于处理数据获取、DOM 操作和资源清理至关重要。
Vue 的生命周期主要分为四个阶段,共 8 个核心钩子函数(Vue 3 对销毁阶段的命名做了修改)。此外还有针对 <keep-alive> 和错误处理的特殊钩子。
1. 四个主要阶段详解
第一阶段:创建 (Creation)
特点:初始化组件,注入依赖,设置响应式数据。此时还没有 DOM。
beforeCreate- 状态:实例刚在内存中被创建,数据观测(Reactivity)和事件配置尚未初始化。
- 可用性:无法访问
data、computed、methods。 - 场景:通常用于插件开发,业务代码中很少使用。
created- 状态:实例创建完成。数据观测、属性和方法的运算、事件回调已配置。
- 可用性:可以访问
data和methods。但此时$el尚不可用(DOM 还没生成)。 - 场景:发送异步请求(API 调用)获取初始数据的最佳时机。
第二阶段:挂载 (Mounting)
特点:编译模板,创建虚拟 DOM,将组件渲染到真实的 DOM 页面中。
beforeMount- 状态:模板编译已完成,render 函数首次被调用。
- 可用性:虚拟 DOM 已经创建,但还没挂载到页面上。
- 场景:极少使用。
mounted- 状态:实例已挂载。
el被新创建的vm.$el替换。 - 可用性:可以访问真实的 DOM 元素。
- 场景:
- 操作 DOM 节点。
- 初始化依赖 DOM 的第三方库(如 ECharts、Mapbox、Swiper)。
- 状态:实例已挂载。
第三阶段:更新 (Updating)
特点:当响应式数据(Data)发生变化时触发。
beforeUpdate- 状态:数据已经更新,但 DOM 还没有重新渲染。
- 可用性:可以访问更新后的数据,但 DOM 还是旧的。
- 场景:在 DOM 更新前访问现有的 DOM(例如手动移除已添加的事件监听器)。
updated- 状态:数据更新完成,DOM 也重新渲染完成。
- 可用性:DOM 是最新的。
- 场景:依赖于 DOM 更新后的操作。
- 注意:避免在此钩子中更改状态(Data),否则可能导致无限循环更新。
第四阶段:销毁/卸载 (Destruction / Unmounting)
特点:组件从父组件中移除,清理资源。
beforeDestroy(Vue 2) /beforeUnmount(Vue 3)- 状态:组件实例即将被卸载。
- 可用性:实例仍然完全可用(数据、方法都能用)。
- 场景:清理工作。例如:清除定时器 (
setInterval)、解绑全局事件 (window.removeEventListener)、销毁第三方实例。
destroyed(Vue 2) /unmounted(Vue 3)- 状态:组件已被卸载。
- 可用性:所有指令解绑,事件监听移除,子实例被销毁。DOM 节点已不存在。
- 场景:通知服务器组件已销毁等后续处理。
2. 特殊生命周期
缓存组件 <keep-alive>
当组件被 <keep-alive> 包裹时,它不会被销毁,而是进入缓存状态。
activated:组件被激活(进入视图)时调用。deactivated:组件被停用(离开视图)时调用。
错误捕获
errorCaptured:捕获一个来自后代组件的错误时被调用。
3. Vue 2 vs Vue 3 对比表
Vue 3 引入了 Composition API (组合式 API),在 setup() 函数中使用生命周期钩子时,需要加上 on 前缀。
| 阶段 | Vue 2 (Options API) | Vue 3 (Options API) | Vue 3 (Composition API / setup) |
|---|---|---|---|
| 创建 | beforeCreate |
beforeCreate |
不需要 (直接写在 setup 中) |
| 创建 | created |
created |
不需要 (直接写在 setup 中) |
| 挂载前 | beforeMount |
beforeMount |
onBeforeMount |
| 挂载后 | mounted |
mounted |
onMounted |
| 更新前 | beforeUpdate |
beforeUpdate |
onBeforeUpdate |
| 更新后 | updated |
updated |
onUpdated |
| 销毁前 | beforeDestroy |
beforeUnmount |
onBeforeUnmount |
| 销毁后 | destroyed |
unmounted |
onUnmounted |
| 激活 | activated |
activated |
onActivated |
| 停用 | deactivated |
deactivated |
onDeactivated |
4. 总结与最佳实践
- 接口请求:放在
created(Vue 2) 或setup(Vue 3) 中。如果请求依赖 DOM 元素,则放在mounted中。 - DOM 操作:必须放在
mounted中。 - 清理资源:定时器和全局事件监听器必须在
beforeUnmount(或onBeforeUnmount) 中清除,防止内存泄漏。 - 父子组件顺序:
- 加载:父
beforeCreate-> 父created-> 父beforeMount-> 子beforeCreate-> ... -> 子mounted-> 父mounted。 - 销毁:父
beforeUnmount-> 子beforeUnmount-> ... -> 子unmounted-> 父unmounted。 - (规律:子组件先挂载,子组件先销毁)
- 加载:父
右滑查看面试常问