恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Vue生命周期核心钩子与实战:从created到unmounted的完整指南

  • 首页
  • 资讯中心
  • /
  • Vue生命周期核心钩子与实战:从created到unmounted的完整指南

相关资讯

Hammer.js 手势识别实战指南:从触摸事件到识别器与避坑经验 2026/10/6 14:28:06
数字日期如何成为节日?从3.16 day看社群纪念日的打造方法 2026/10/6 14:28:06
肝脏病理病变检测数据集:YOLO训练与实战避坑指南 2026/10/6 14:23:06

最新资讯

Win10/Win11本地部署ASP报修系统实战指南
Python安装后终端没反应?排查环境变量与ConPTY问题
K1622-VB N沟道MOS管深度解析:从参数、驱动到电机驱动实战
用Claude Skill将需求文档自动生成测试用例与Playwright脚本的实践
告别假交付:ITIL4发布计划如何从流程文档变成可执行工程承诺
OpenShell 深度解析:Windows 开始菜单定制与效率优化实战

今日推荐

2026 AI 开发全家桶落地指南:TaoToken 统一 Key 打通 IDE 插件、Agent 与自动化代码审查全链路配置实测
MR25H40CDF+STM32F031C6工业级高可靠数据存储方案
MRAM+STM32工业断电数据保全实战指南

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Vue生命周期核心钩子与实战:从created到unmounted的完整指南

发布时间:2026/10/6 14:28:06
Vue生命周期核心钩子与实战:从created到unmounted的完整指南 1. 为什么死活搞不懂Vue生命周期先建立心智模型如果你刚学Vue或者学了一阵子但总觉得“生命周期”这玩意儿只在面试题里出现那我敢打赌你大概率遇到过下面这种场景接口数据明明请求成功了console.log也打印了可页面就是不动。想在mounted里拿DOM元素操作一下结果拿了个undefined。定时器在销毁页面之后还在疯狂输出控制台刷得跟弹幕一样。这些破事儿表面上看是各种奇怪bug本质上全都指向同一个问题你不清楚Vue从创建到销毁这个过程中每个节点到底发生了什么。Vue生命周期简单说就是组件从“被创建”到“被销毁”的整个过程。Vue在这个过程的不同阶段给了我们不同的钩子函数英文叫hooks让我们可以在特定时机执行自己的代码。这些钩子就像定时器加条件触发的一套指挥系统——到点了就弹出一个窗口问你要不要执行点什么。这篇文章不打算给你背书式的罗列每个钩子而是用实际业务场景把整个生命周期串起来讲。不管你刚入门还是准备面试看完之后至少能搞清楚该把请求放哪、该在哪操作DOM、该在哪清理副作用、为什么别人写的代码总是比我少踩坑。先说明一点这篇文章主要基于Vue 3的写法但对于Vue 2的读者同样适用因为两者只是部分钩子名称改了个名字比如destroyed变成了unmounted逻辑本身是一致的。文末我会用一个表格把对应关系整理清楚。2. 九个钩子每个背后的核心命题都不一样先花点时间把生命周期流程在脑子里过一遍。Vue 3的组件生命周期被拆得很细其实归纳下来就是创建、挂载、更新、卸载四个大阶段加上一个开发者常用的错误捕获钩子。这里我想用一句话帮助记忆组件从“没有”到“有”再到“能变”最后到“没有”这中间每个状态切换都有对应的钩子。2.1 创建阶段数据从无到有创建阶段包含两个钩子beforeCreate和created。beforeCreate触发的时候组件实例刚刚被创建data、methods、computed这些统统还没初始化你在里面几乎什么都干不了。这个钩子在实际开发中用得极少只有在某些特殊场景比如插件或混入需要在实例初始化之前做一些操作才会用到。到了createddata和methods已经准备好可以访问和修改数据了。但注意此刻模板还没有编译DOM还没有生成this.$el是undefined。你在这个阶段可以进行数据初始化、请求首屏数据、设置一些与DOM无关的初始逻辑。为什么首屏数据请求通常放created而不是mounted因为created触发时数据响应式系统已经就绪你在这里改数据Vue会在后续挂载过程中直接使用最新数据渲染一次到位。如果在mounted里再请求数据并修改往往意味着组件要先按空数据渲染一版再被动更新成有数据的一版虽然最终结果一样但多了一次渲染过程。2.2 挂载阶段DOM从无到有beforeMount触发时模板已经编译完成但还没有真正插入浏览器DOM。在这里你依然拿不到渲染后的DOM节点。mounted是整个生命周期里最重要的钩子之一。此时组件已经完成挂载DOM可以访问了你可以在这里操作DOM、初始化第三方库、绑定事件监听器。我见过很多把图表初始化放错位置的人——在created里调用一个需要document.getElementById的ECharts初始化方法结果getElementById返回null然后开始怀疑是不是库的原因。记住一个铁律只要你的代码依赖了真实DOM就放进mounted或者更靠后的钩子。2.3 更新阶段数据驱动视图变化beforeUpdate在数据发生变化、DOM将要被更新之前触发。它适合在更新前访问现有的DOM状态比如记录滚动位置、保存用户输入的临时状态。updated则在DOM更新完成后触发适合需要依赖新DOM状态的场景。这里有个容易误解的点很多人以为每次修改数据都会触发update钩子其实是错的。只有数据变化引发视图变化时才会触发。你给一个不渲染到模板上的数据赋新值并不会触发beforeUpdate和updated。2.4 卸载阶段该清理的别留Vue 3中叫beforeUnmount和unmountedVue 2中对应的是beforeDestroy和destroyed。beforeUnmount触发时组件实例还完全可用适合做最后的清理工作。unmounted触发后组件实例已经销毁所有东西都不再可用。你在这里需要解绑自定义事件、清除定时器、关闭WebSocket连接、销毁图表实例。这部分的坑非常高频后面我会单独展开讲。2.5 错误捕获与缓存激活除了上面八个还有两个实际工作中也经常遇到的errorCaptured用于捕获后代组件抛出的错误结合项目里的全局错误监控来做上报很实用activated和deactivated则专门配合keep-alive使用组件被缓存后再次进入时触发activated离开时触发deactivated。这里有一个值得提的点keep-alive缓存的组件created和mounted只会在首次渲染时执行一次后续切换页面如果每次都往列表页的created里塞请求你会发现数据永远停留在第一次的样子。正确做法是把请求逻辑挪到activated里。为了让你快速对照我整理了一张表钩子名称触发时机能否访问DOM典型场景beforeCreate实例初始化前不能极少使用用于插件或混入的预初始化created实例创建完成数据和事件可用不能首屏数据请求、非DOM依赖的初始化beforeMount模板编译完成未挂载不能极少使用mounted组件挂载完成DOM可用能初始化第三方库、操作DOM、绑定全局事件beforeUpdate数据变化DOM更新前能获取更新前的DOM状态updated数据变化DOM更新完成能需要基于新DOM做后续操作beforeUnmount组件销毁前能清理定时器、解绑事件unmounted组件销毁后不能最后收尾所有清理逻辑也可以放这errorCaptured捕获后代组件错误能错误上报和降级处理activated被keep-alive缓存后重新进入能缓存页面数据刷新这张表建议收藏遇到问题不知道往哪放代码的时候先来这里查一下触发条件。3. 父子组件到底谁先谁后顺序背后的设计逻辑很多人面试被问生命周期答到钩子名和作用就卡壳了。但其实面试官真正想听的不只是钩子列表而是能不能讲清楚整个流程的先后关系。特别是父子组件的生命周期执行顺序几乎是必考题。先直接给出结论。假设有一个父组件Father里面引用了子组件Child加载过程中的完整顺序是父组件的beforeCreate- 父组件的created- 父组件的beforeMount- 子组件的beforeCreate- 子组件的created- 子组件的beforeMount- 子组件的mounted- 父组件的mounted注意一个反直觉的点不是父组件先挂载完再轮到子组件。父组件的挂载需要等待所有子组件挂载完成后才宣布完成。子组件的生命周期要先行完毕父组件的mounted才会触发。为什么这么设计因为父组件的挂载本质上包含“把子组件渲染成DOM并放进自己的视图里”。如果父组件先挂载了子组件还没出来那父组件的mounted状态就是残缺的这个时序在逻辑上不成立。这个先后顺序在开发中有实打实的用处。举个例子如果你在父组件的mounted里想读取子组件的数据此时子组件的mounted已经执行过了通过ref引用是可以直接拿到数据的。反过来如果你在子组件的mounted里尝试读取父组件的DOM内容父组件的mounted还没执行但父组件的DOM结构其实已经存在了一部分。这个细节要靠自己调试的时候感受多跑几次就记住了。更新阶段也有顺序。父组件数据变化导致重新渲染时顺序是父组件beforeUpdate- 子组件beforeUpdate- 子组件updated- 父组件updated。理念和挂载一致父级更新要等子级更新完成才算完成。销毁则反过来父组件的beforeUnmount触发后子组件的beforeUnmount和unmounted依次执行最后才是父组件的unmounted。有点像“领导先发出解散通知各小组收拾完东西领导最后关灯走人”。另外说一个容易被忽略的点如果你在父组件里用插槽slot插入了内容这块插槽内容的生命周期归谁管答案是归父组件管。因为插槽的内容是在父组件作用域里编译的它的数据绑定来自父组件不是子组件。所以插槽内容的created、mounted跟着父组件走子组件的生命周期对插槽内部逻辑没有直接控制力。这也是为什么有时候你在子组件mounted里想操作插槽内容找不到DOM的原因——它不是子组件的孩子是父组件塞进来的孩子。4. 高频业务场景数据请求、图表初始化、事件绑定该往哪放理论讲完下面全部是实战。这部分我把自己做过的项目里踩过的坑和验证过的方案整理出来直接告诉你“该往哪放”以及“为什么”。4.1 首屏数据请求created还是mounted先说结论常规首屏数据请求放created。原因是这个阶段data已经是响应式的你请求到数据后直接赋值组件会在随后的挂载渲染中使用这些数据一次性渲染出完整页面。不需要经历“先渲染空壳再请求数据更新”的流程。但有一种情况我建议放mounted那就是请求的数据会立刻触发大量DOM操作时。比如你有一个地图组件数据回来之后需要在地图上打几百个点如果放在created里修改数据地图还没初始化你得等mounted到了再补一次绘制。这种情况下不如直接在mounted里统一处理逻辑更加集中。项目里具体放哪可以根据数据与DOM的耦合程度来判断没有绝对标准。实际操作里我自己的习惯是纯数据展示的请求放created需要和DOM或者第三方库联动的请求放mounted。放created的请求到mounted时数据基本已经就绪配合v-if或者默认值渲染体验流畅很多。4.2 第三方库初始化为什么必须在mounted你肯定遇到过这种情况项目里要用ECharts画图表或者接入Mapbox渲染地图在created里调用初始化方法报错说找不到某个DOM节点。原因前面已经提到了created阶段DOM还不存在。这些库几乎都需要一个容器节点才能完成初始化所以必须在mounted里写。比如ECharts的经典写法是mounted() { const chartDom document.getElementById(main); this.myChart echarts.init(chartDom); this.myChart.setOption({ // 配置项 }); }注意这里还有个细节如果你在mounted里初始化了图表组件销毁时要记得disposebeforeUnmount() { if (this.myChart) { this.myChart.dispose(); this.myChart null; } }不销毁图表会怎样轻则内存泄漏重则组件重新渲染时因为容器已被销毁而报错。我现在只要遇到项目页面反复切换后越来越卡、内存占用持续增长第一反应就是去检查有没有遗漏的图表实例和事件监听器。4.3 事件监听和定时器卸载阶段必须清理的三大件我复盘过自己写过的最糟糕的一版代码就是在一个列表组件里监听了scroll事件组件卸载时没有移除监听结果每次进入页面再退出监听器就多一份。用户滚动几次之后页面开始明显掉帧。清理对象基本是这三类window或document级别的全局事件监听用addEventListener添加的必须用removeEventListener移除setInterval和setTimeout必须clearInterval或clearTimeoutWebSocket连接、EventSource等实时通道需要close这里推荐两个常见做法。一个是在beforeUnmount里手动清理created() { window.addEventListener(resize, this.handleResize); this.timer setInterval(() { /* 业务代码 */ }, 1000); }, beforeUnmount() { window.removeEventListener(resize, this.handleResize); clearInterval(this.timer); }另一个更优雅的做法是用onScopeDispose或者watchEffect里自带的自动清理机制适合Vue 3组合式API下使用。比如用watchEffect监听某个响应式数据当组件卸载时副作用会自动被清理不需要手动操心。我个人现在更倾向于在组合式API里处理逻辑时尽量用自动清理能力来兜底但那些addEventListener绑定到全局对象的还是老老实实在卸载阶段手动解绑别偷懒。4.4 路由参数变化导致组件复用created不动了怎么办这是另一个高频坑。在Vue Router中从/user/1跳转到/user/2如果两个路由使用的是同一个组件实例组件不会重新创建也就是说created和mounted不会再次执行。页面会显示残留的上一个ID的数据。热搜里“vue动态路由”“vue路由参数”相关的问题很多最终都会绕到这个点上来。解决思路有几种用watch监听$route的变化在回调里重新拉取数据用:key绑定路由参数让路由参数变化时强制重新创建组件在beforeRouteUpdate导航守卫里做处理以watch方案为例这是最直接的watch: { $route.params.id: { handler(newId) { this.fetchData(newId); }, immediate: true } }immediate: true是为了保证首次进入也能执行一次。用:key方案则更“粗暴”router-view :key$route.fullPath /这样路由地址一变化整个组件重新走一遍完整的生命周期。代价是状态全部重建像表单输入内容、滚动位置都会丢失。具体取舍要看业务场景——如果是列表页跳详情页重新创建完全没问题如果是同页签切换参数建议还是用watch保持页面状态。4.5 Vue 3组合式APIonMounted、onUnmounted的使用注意Vue 3里生命周期钩子变成了onMounted、onCreated这些导入函数。特别注意Vue 3中created不再有对应的onCreated因为组合式API里setup本身执行时机就相当于在created之前你在setup里写的代码天然处于“数据已初始化但未挂载”的阶段。setup里可以直接访问this吗不建议。组件实例在setup执行期间还没有完全创建好用getCurrentInstance()可以拿到内部实例但更推荐的做法是直接依赖传入的props、context执行逻辑。组合式API生命周期函数的调用位置也有限制必须在组件的setup函数内同步调用这样才能注册到当前组件实例上。你在一个异步回调里调用onMountedVue会发出警告因为此时组件实例的上下文已经丢失。5. 面试官最爱问的几个生命周期问题逐一拆解热搜词里“vue面试题”出现的频率非常高。生命周期相关是面试里的老演员翻来覆去就是几个问法。我用模拟对话的方式还原一下顺便给你答题的思路。5.1 问created和mounted的区别是什么为什么请求数据放created而不是mounted标准答法分两层。第一层说时机区别created时数据初始化完成但DOM未生成mounted时DOM已经挂载可访问。第二层说使用建议请求数据放created是为了让数据在挂载前就就绪减少一次视图渲染迭代放mounted也可以但意味着组件至少有一次“空数据”渲染过程。如果面试官追问“到底哪种更好”可以说取决于是否依赖DOM。不依赖DOM的初始化逻辑优先放created依赖DOM的处理放mounted。没有绝对正确答案能讲清楚取舍就是好的回答。5.2 问父组件和子组件的生命周期执行顺序为什么回答这个题要把顺序背熟并且连更新阶段、销毁阶段一起说。前面第3节已经给过完整顺序建议原封不动背下来。要解释“为什么是这种顺序”的话抓住一个核心逻辑父组件的挂载依赖子组件挂载完成子组件必须先结束自身生命周期父组件才能完成完整的挂载声明。5.3 问在mounted里修改数据会触发update吗会不会导致死循环会触发。mounted执行后如果修改了响应式数据Vue会进入更新流程也就是说beforeUpdate和updated会依次被调用。至于死循环看你改的数据是否被模板渲染。如果某个数据在模板里用到了你在updated里又去修改它而且没有条件控制就会“改数据 - 触发更新 - 进入updated - 再改数据 - 再触发更新”无限循环下去。我之前写过一段代码在updated里根据组件宽度进行自适应布局宽度一变又赋值回去结果页面直接卡死。后来改成在watch里加了一个防抖或者在updated里判断第一个值没有变化才执行才解决。任何时候在更新钩子里修改数据都要先问自己这次修改会不会再次触发更新5.4 问keep-alive组件下生命周期有何不同什么时候用activatedkeep-alive会让被包裹的组件在切换时不被销毁而是被缓存下来。因此组件的created和mounted只执行一次。再次切回时不会重新走创建流程而是触发activated切走时触发deactivated。使用场景非常明确需要频繁切换、保持页面状态的场景。比如列表页滚到一半切到详情页再返回列表想保持滚动位置和数据keep-alive就是解决方案。配合activated做数据刷新配合deactivated做状态暂存比重新创建组件性能好得多。5.5 问Vue 2和Vue 3的生命周期改名了具体对应关系是什么Vue 3把beforeDestroy改成了beforeUnmountdestroyed改成了unmounted。语义更准确组件不一定是“被销毁”更多时候是“从DOM上卸载”。其余钩子名字保持不变。另外Vue 3组合式API引入了onBeforeMount、onMounted等命名但选项式API里以before开头的钩子名仍是beforeMount、beforeUpdate这类写法。这块如果面试时能主动提一句“Vue 3中卸载钩子语义更适合keep-alive场景对于非缓存组件而言unmounted和destroyed本质相同”面试官会觉得你是真用过。5.6 问请求接口返回后组件已经销毁了怎么办这是一个稍进阶的问题考查对异步生命周期的理解。场景是这样的请求发出后用户很快切换了页面组件被卸载此时请求返回并尝试给已经销毁的组件实例赋值数据Vue会警告“Attempting to use a destroyed component instance”或者悄悄失败。推荐用AbortController配合fetch来实现取消请求。axios的话有两种思路一种是组件卸载时通过cancelToken取消另一种更省事的是用一个isUnmounted标志位let isUnmounted false; async function fetchData() { const data await api.get(/xx); if (isUnmounted) return; // 正常赋值逻辑 } onBeforeUnmount(() { isUnmounted true; });有耐心的话在真实项目里把axios实例封装成“可取消请求”的形式通过signal传递取消信号资源释放更干净。不过大多数中小项目里标志位已经够用。6. 实际开发中的常见坑以及排查思路开篇说的那些“页面不动、DOM拿不到、定时器清不掉”的现象这一节统一给出排查思路。每一个坑都可以当成一次小型的代码考古现场。6.1 坑一页面数据变了视图纹丝不动排查方向不要先怀疑生命周期出错先确认数据本身是不是响应式的。Vue 3中直接给普通对象添加新属性或者通过索引修改数组元素并不会触发视图更新。这不是生命周期的问题是响应式系统的问题但很多人会跑到生命周期里去找原因。Vue 3推荐用reactive或者组合式API里保持数据结构完整。如果你在模板里渲染的是一个对象的某个字段而这个字段是后加的建议提前在data中声明好初始值哪怕是空字符串也能保证它的响应式状态。6.2 坑二DOM明明渲染了但mounted里操作时报错有一种典型报错是Cannot read properties of null (reading style)。原因通常是条件渲染。你在模板里用v-if控制了一段DOM的显示初始状态是falsemounted触发时这段DOM根本不存在。解决方法有几种把初始化逻辑放到nextTick里this.$nextTick(() { // DOM已更新可以安全操作 });或者使用watch加上immediate和flush: post选项确保DOM更新后再执行回调。在Vue 3组合式API下可以这么写watch( () props.show, (val) { if (val) { // 此时DOM刚渲染 } }, { immediate: true, flush: post } );6.3 坑三定时器关了回调还在跑排查步骤很简单检查清理动作是否真的执行了。最常见的原因是清理逻辑写在unmounted里但组件被keep-alive缓存了没有走销毁流程。这时必须改用deactivated清理或者在activated里重新开定时器。另一个原因是你用了箭头函数定义了回调导致clearInterval时传入的句柄和创建时不一致。写成this.timer setInterval(() {}, 1000);清理时写clearInterval(this.timer)注意this的指向问题确保同一个实例。6.4 坑四子组件数据没更新完父组件就想读这个坑容易出现在“点击按钮父组件弹窗弹窗里是子组件弹窗刚显示时就尝试读取子组件内部的表单数据”这类场景。弹窗显示完成后子组件可能才刚开始初始化父组件紧接着就读拿到的是空值。解决方案是让父组件等待子组件emit信号或者用nextTick延迟读取再不行就在弹窗组件里加一个ready状态通过v-if控制等子组件真正mounted后再透出事件。6.5 坑五打包部署后生命周期表现与本地不一致有个真实案例项目本地跑没有任何问题打包部署到服务器后页面首次进入白屏报错信息指向某个mounted里的DOM操作。排查后发现问题出在异步加载组件时DOM尚未完全渲染本地开发环境下调试器速度偏慢给了Vue“喘息”的机会线上环境加载更快时序差异暴露了问题。这类问题的通用排查法把所有依赖DOM的逻辑统统包一层nextTick或者改成flush: post的watch。另外检查部署环境下是否有同步阻塞脚本影响了生命周期执行的顺序。类似场景还有基于Spring Boot这类后端框架做的整合部署如果前端是静态资源嵌入后端容器中加载顺序会受后端安全拦截器、静态资源压缩策略影响。我之前遇到的一次白屏就是后端对压缩包内JS做了缓存版本控制导致浏览器加载到的是旧版本逻辑生命周期里调用的新API方法不存在。遇到部署环境问题先强刷缓存再看控制台报错最后检查静态资源的cache策略。7. 写在最后的实操建议全是经验总结踩过坑换来的。第一个建议是把“该在哪个生命周期做什么”当成一种代码审查习惯。以后每次写初始化逻辑先在脑子里过一遍这个执行时机是否合理。不要只满足于“能跑”生命周期这东西现在是能跑但产品经理一旦让你加个轮询、加个缓存恢复、加个埋点上报时序不对的代码立刻会崩成一团。第二个建议是不要害怕在mounted里操作DOM但要学会区分“DOM操作”和“数据操作”的边界。数据相关的内容往created和watch放DOM操作往mounted和nextTick放两者混在一起时优先考虑数据先行。第三个建议也是我认为最重要的学习生命周期不要只背钩子清单要去调试。在Vue的devtools里打开组件树观察从创建到卸载整个过程中每个阶段的渲染记录。或者直接在代码里每个钩子打印一行日志跑一遍完整的业务流你会直观感受到顺序的微妙之处。这个习惯比你看一百篇解析文章都有效。如果你是一个新手刚开始别被这些钩子的数量吓到。实际开发中80%的情况下你只需要created、mounted、beforeUnmount三个钩子。把这三个吃透、用对再慢慢熟悉其他钩子在特定场景中的作用就足够应付绝大多数日常开发了。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号