目录
- 前言
- [一、Vue2 与 Vue3 的生命周期图](#一、Vue2 与 Vue3 的生命周期图)
- [二、vue2、vue3 实例的生命周期及其在 setup 中的对照表](#二、vue2、vue3 实例的生命周期及其在 setup 中的对照表)
- 三、父子组件生命周期执行顺序对比总表
-
- [1、为什么 mounted 是"子 → 父"?](#1、为什么 mounted 是“子 → 父”?)
- [2、为什么 updated 是"子 → 父"?](#2、为什么 updated 是“子 → 父”?)
- [3、为什么卸载是"父 beforeUnmount → 子 beforeUnmount → 子 unmounted → 父 unmounted"?](#3、为什么卸载是“父 beforeUnmount → 子 beforeUnmount → 子 unmounted → 父 unmounted”?)
前言
- Vue2 与 Vue3 Options API 的生命周期在使用方式上基本一致,只是 Vue3 在命名上更语义化,并新增了调试相关钩子;
- 而在 Composition API 中,生命周期不再作为组件配置项存在,而是通过 onMounted 等函数在 setup 中注册,使生命周期能够和逻辑模块一起被复用,这是 Vue3 架构设计上的一次重大升级。
一、Vue2 与 Vue3 的生命周期图
vue2 的生命周期图(左/上)和 vue3 的生命周期图(右/下)------摘自 Vue 官网:


二、vue2、vue3 实例的生命周期及其在 setup 中的对照表
| 阶段分类 | 触发时机说明 | Vue2 | Vue3(Options API) | Vue3(Composition API) | 关键差异说明 |
|---|---|---|---|---|---|
| 创建阶段 | 组件实例刚被创建,数据观测尚未完成 | beforeCreate | beforeCreate | ❌ 无(被 setup 取代) | Composition API 不再暴露此阶段 |
| data、props、methods 初始化完成 | created | created | ❌ 无(被 setup 取代) | setup 同时承担 beforeCreate + created 职责 | |
| Vue3 组合式入口 | ❌ | ❌ | setup() | 在所有生命周期之前执行,但在 beforeMount 之前结束 | |
| 挂载阶段 | render 首次执行完成,DOM 尚未挂载 | beforeMount | beforeMount | onBeforeMount | 执行时虚拟 DOM 已生成 |
| DOM 创建并插入页面完成 | mounted | mounted | onMounted | 可以安全访问 DOM | |
| 更新阶段 | 响应式数据变化,DOM 尚未更新 | beforeUpdate | beforeUpdate | onBeforeUpdate | 适合读取旧 DOM 状态 |
| DOM 更新完成 | updated | updated | onUpdated | DOM 已是最新,避免在此修改响应式数据 | |
| 卸载阶段 | 组件即将被移除,实例仍存在 | beforeDestroy | beforeUnmount | onBeforeUnmount | Vue3 改名为 Unmount,更准确表达"卸载" |
| 组件已移除,响应式 effect 停止 | destroyed | unmounted | onUnmounted | Vue3 生命周期结束标志 | |
| 缓存组件 | 组件被 KeepAlive 缓存并重新激活 | activated | activated | onActivated | 组件未销毁,仅重新插入 DOM |
| 组件被缓存移出页面但未销毁 | deactivated | deactivated | onDeactivated | 常用于页面状态缓存 | |
| 错误处理 | 捕获子组件错误 | errorCaptured | errorCaptured | onErrorCaptured | 可阻止错误继续向上传播 |
| 调试追踪(Vue3新增) | render 过程中依赖被收集时触发 | ❌ | renderTracked | onRenderTracked | 用于调试"依赖是如何收集的" |
| 响应式依赖触发组件重新渲染时 | ❌ | renderTriggered | onRenderTriggered | 用于调试"是谁触发了更新" |
额外补充对比维度:
| 对比维度 | Vue2 | Vue3 Options API | Vue3 Composition API |
|---|---|---|---|
| 生命周期书写方式 | 组件选项对象中的方法 | 与 Vue2 相同 | setup 中以函数形式注册 |
| 是否依赖 this | 强依赖 | 强依赖 | ❌ 不依赖 this |
| 生命周期复用能力 | 依赖 mixin(易冲突) | mixin 仍可用 | ✅ 可在 composable 中复用 |
| 类型推导友好度 | 一般 | 较好 | ✅ 最佳(天然 TS 友好) |
| created 阶段是否存在 | ✅ | ✅ | ❌ 被 setup 替代 |
| beforeDestroy / destroyed 命名 | destroy | 改为 unmount | 改为 unmount |
三、父子组件生命周期执行顺序对比总表
| 阶段 | Vue2 执行顺序 | Vue3 Options API 执行顺序 | Vue3 Composition API 执行顺序 | 规律说明 |
|---|---|---|---|---|
| 创建阶段开始 | 父 beforeCreate | 父 beforeCreate | 父 setup | 父组件实例先创建 |
| 父 created | 父 created | 父 setup 结束 | setup 代替 created | |
| 子 beforeCreate | 子 beforeCreate | 子 setup | 然后才创建子组件 | |
| 子 created | 子 created | 子 setup 结束 | 子组件完成初始化 | |
| 挂载前 | 父 beforeMount | 父 beforeMount | 父 onBeforeMount | render 生成 VNode 后触发 |
| 子 beforeMount | 子 beforeMount | 子 onBeforeMount | 子组件准备挂载 | |
| 挂载完成 | 子 mounted | 子 mounted | 子 onMounted | ⭐ DOM 是从内到外挂载 |
| 父 mounted | 父 mounted | 父 onMounted | 父最后拿到完整 DOM 树 | |
| 更新阶段开始 | 父 beforeUpdate | 父 beforeUpdate | 父 onBeforeUpdate | 响应式数据变更先影响父 |
| 子 beforeUpdate | 子 beforeUpdate | 子 onBeforeUpdate | 子组件接收新 props | |
| 更新完成 | 子 updated | 子 updated | 子 onUpdated | 子先完成 DOM 更新 |
| 父 updated | 父 updated | 父 onUpdated | 父最后完成更新 | |
| 卸载阶段开始 | 父 beforeDestroy | 父 beforeUnmount | 父 onBeforeUnmount | 父决定不再渲染子 |
| 子 beforeDestroy | 子 beforeUnmount | 子 onBeforeUnmount | 子开始清理 | |
| 卸载完成 | 子 destroyed | 子 unmounted | 子 onUnmounted | 子先被销毁 |
| 父 destroyed | 父 unmounted | 父 onUnmounted | 父最后销毁 |
执行顺序在三套体系里本质是一样的,变的只是 API 形式。
1、为什么 mounted 是"子 → 父"?
DOM 挂载顺序是:
typescript
父 render
└─ 创建子 VNode
└─ patch 子 → 生成子 DOM
父 DOM 才最终完成。
所以:
- 子 mounted 一定先于父 mounted
父组件在 mounted 时,才能确保子 DOM 全部可用。
2、为什么 updated 是"子 → 父"?
更新流程:
typescript
父组件响应式变化
→ 父 beforeUpdate
→ render 新 VNode
→ patch 子组件
→ 子 beforeUpdate
→ 子 updated
→ 父 updated
子 DOM 更新完成后,父才算更新完成。
3、为什么卸载是"父 beforeUnmount → 子 beforeUnmount → 子 unmounted → 父 unmounted"?
卸载过程:
typescript
父组件决定移除子
→ 父 beforeUnmount
→ 卸载子组件
→ 子 beforeUnmount
→ 子 unmounted
→ 父 unmounted
父是"发起者",子是"被处理者"。