Vue2Vue3:生命周期全景对比深度分析
本文完整梳理 Vue2 Options API、Vue3 Options API、Vue3 Composition API(setup)生命周期钩子,采用多维度表格对比,区分兼容差异、执行时机、使用场景、注意事项,同时讲解变更逻辑、废弃 API、替代方案,适用于项目迁移、面试复习、架构选型参考。
前置基础概念
生命周期:组件从创建、挂载、更新到销毁的完整流程框架,框架内置回调钩子,允许开发者在特定阶段执行自定义逻辑。
版本边界说明
Vue2:
Options API唯一标准Vue3 两套写法:
Options API:最大程度兼容 Vue2(保留旧钩子名称,存在别名调整)
Composition API(
<script setup>):全新函数式钩子,无this,推荐新项目使用重要变化:Vue3 引入创建阶段重构,移除
beforeCreate / created对应组合式钩子,统一使用setup;销毁类钩子重命名。
一、生命周期总流程时序对比表
表 1:完整生命周期执行顺序全景(Vue2 Options vs Vue3 Options vs Vue3 Composition)
阶段 | Vue2 Options API | Vue3 Options API | Vue3 Composition API(script setup) | 核心执行时机说明 |
创建阶段 | beforeCreate | beforeCreate | setup(执行早于所有钩子) | 实例初始化,观测数据、事件配置,DOM 尚未生成,无法访问 |
created | created | setup | 实例创建完成,数据响应式就绪;仍未挂载 DOM,无真实 DOM 节点 | |
挂载阶段 | beforeMount | beforeMount | onBeforeMount | DOM 挂载开始,模板编译完成,虚拟 DOM 就绪,页面未渲染到浏览器 |
mounted | mounted | onMounted | DOM 挂载完成,可操作真实 DOM、访问 | |
更新阶段 | beforeUpdate | beforeUpdate | onBeforeUpdate | 响应式数据发生变化,虚拟 DOM 开始重新渲染,旧 DOM 还未更新 |
updated | updated | onUpdated | DOM 更新完成,可获取最新 DOM;⚠️禁止直接修改会触发更新的响应式数据 | |
销毁阶段 | beforeDestroy | beforeUnmount | onBeforeUnmount | 组件销毁启动,实例仍然可用,定时器、事件监听建议在此清除 |
destroyed | unmounted | onUnmounted | 组件实例销毁,DOM 移除,响应式监听、子实例全部解除绑定 | |
缓存组件专属 | activated | activated | onActivated |
|
deactivated | deactivated | onDeactivated |
| |
错误捕获 | errorCaptured | errorCaptured | onErrorCaptured | 捕获后代组件抛出的错误 |
⚠️关键时序结论: Vue3
setup早于 beforeCreate、created;在组合式 API 中不存在单独的onBeforeCreate/onCreated钩子,逻辑全部写在setup内部。
二、钩子名称变更对照表(迁移重点)
表 2:销毁钩子重命名变更(Vue2 → Vue3 破坏性变更)
Vue2 旧名称 | Vue3 Options API 名称 | Vue3 Composition API 钩子 | 变更原因 |
beforeDestroy | beforeUnmount | onBeforeUnmount | 语义统一:不再叫 “销毁实例”,强调DOM 卸载,服务端渲染概念对齐 |
destroyed | unmounted | onUnmounted | 同上 |
注意:Vue3 Options API不再兼容
beforeDestroy / destroyed,直接使用新名称,写旧名不会执行!
三、Options API 与 Composition API 钩子一一映射表
表 3:钩子一对一映射清单(开发迁移查询)
Vue3 Options API | Vue3 Composition API 导入钩子函数 |
beforeCreate | 无对应钩子,逻辑写在 setup 顶层 |
created | 无对应钩子,逻辑写在 setup 顶层 |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
activated | onActivated |
deactivated | onDeactivated |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked(调试) |
renderTriggered | onRenderTriggered(调试) |
补充:Vue3 新增两个调试专用钩子,Vue2 不存在:onRenderTracked:追踪响应式依赖收集;onRenderTriggered:追踪触发重新渲染的数据,仅用于调试。
四、关键能力限制对比表(开发避坑核心)
表 4:各阶段钩子可用能力对比
钩子 | 是否可访问响应式 data | 是否可访问 DOM/$el | 是否存在 this | 适合业务场景 |
beforeCreate(Vue2/Vue3 Options) | ❌ data 未初始化 | ❌ | ✅ this 存在,但无法读取 data | 极少使用 |
created(Vue2/Vue3 Options) | ✅ | ❌ | ✅ | 发起接口请求、初始化数据(无 DOM 操作) |
setup(Composition) | ✅(ref/reactive) | ❌ | ❌ 禁止使用 this | 变量定义、创建监听、基础初始化 |
beforeMount | ✅ | ❌ | ✅ | 极少使用,几乎可以被 created 替代 |
mounted / onMounted | ✅ | ✅ | ✅(Options) / ❌(Composition) | DOM 操作、第三方实例初始化(echarts/map)、首次请求 |
beforeUpdate | ✅ | ✅(旧 DOM) | ✅ | 获取更新前 DOM 状态,很少使用 |
updated | ✅ | ✅(最新 DOM) | ✅ | 基于更新后 DOM 操作;避免修改响应式数据,防止无限循环 |
beforeUnmount / onBeforeUnmount | ✅ | ✅(DOM 还未删除) | ✅ | 清除定时器、移除全局事件、销毁第三方实例(最重要清理钩子) |
unmounted / onUnmounted | ✅ | ❌ DOM 已移除 | ✅ | 兜底清理,不推荐作为主要清理位置 |
activated | ✅ | ✅ | ✅ | keep-alive 进入页面,刷新数据、重启轮询 |
deactivated | ✅ | ✅ | ✅ | keep-alive 离开页面,暂停轮询、保存页面临时状态 |
五、代码示例对照表格
表 5:同一份业务逻辑,三种写法代码对照
场景:组件挂载请求接口;组件销毁清除定时器
<!-- Vue2 Options API --> <script> export default { data(){ return { timer:null } }, mounted(){ this.fetchData(); this.timer = setInterval(()=>{},1000) }, beforeDestroy(){ clearInterval(this.timer) } } </script><!-- Vue3 Options API --> <script> export default { data(){ return { timer:null } }, mounted(){ this.fetchData(); this.timer = setInterval(()=>{},1000) }, beforeUnmount(){ clearInterval(this.timer) } } </script><!-- Vue3 script setup Composition API --> <script setup> import {onMounted,onBeforeUnmount} from 'vue' let timer = null const fetchData = ()=>{} onMounted(()=>{ fetchData() timer = setInterval(()=>{},1000) }) onBeforeUnmount(()=> clearInterval(timer)) </script>六、高频易踩坑问题汇总表
表 6:生命周期经典坑点对比
问题场景 | Vue2 表现 | Vue3 表现 | 解决方案 |
在 created 操作 DOM | ❌ 获取不到 $el | ❌ 获取不到 $el | DOM 操作统一移入 mounted /onMounted |
keep-alive 组件,离开触发销毁钩子 | ❌ 不会执行 beforeDestroy/destroyed | ❌ 不会执行 beforeUnmount/unmounted | 使用 activated、deactivated 管理轮询 |
在 updated 内修改响应式变量 | 极易无限更新循环 | 极易无限更新循环 | 增加判断条件,尽量不在更新钩子修改数据 |
Vue2 beforeDestroy 直接迁移 Vue3 | 不执行,钩子名称失效 | 钩子不触发,无报错静默失败 | 替换为 beforeUnmount |
Composition 中尝试使用 onCreated | API 不存在,控制台警告 | 无该函数 | 初始化逻辑直接写在 setup 顶层 |
异步组件生命周期时序 | 延迟执行 mounted | 逻辑一致,异步加载完成才触发挂载 | 无需修改 |
七、服务端渲染 SSR 环境差异补充
SSR 环境:mounted、onMounted 仅在客户端执行,服务端渲染阶段不会触发;
created、setup 在服务端、客户端都会执行;
因此:所有 DOM 相关、浏览器 API(window/document)代码,必须放在 mounted 系列钩子,防止 SSR 报错。
八、核心总结
8.1、最大变更点
1、Vue3 销毁钩子改名:
beforeDestroy → beforeUnmount,destroyed → unmounted2、Composition API 取消独立 created/beforeCreate,全部合并到 setup
8.2、写法选型建议
1、老项目 Vue2 迁移 Vue3:Options API 优先修改钩子名称;
2、新项目 Vue3:统一使用
<script setup>+ Composition 生命周期钩子;
8.3、开发规范
1、数据请求:无 DOM 依赖 → created/setup;依赖 DOM → mounted
2、资源清理:统一放置
beforeUnmount / onBeforeUnmount3、keep-alive 缓存组件:使用 activated/deactivated 管理轮询与页面状态
如果你需要,我可以把整篇文章整理成适合直接发布到 CSDN 的完整排版版本(增加标题层级、Markdown 优化、可直接复制发布)。
