企业级跨平台移动应用开发实战之Uniapp生命周期详解和避坑指南
书接上篇,我们今天继续来学习一下 UniApp 应用的生命周期以及和VUE生命周期的区别与应用,以及常见避坑指南和开发实践。
此系列文章将带领你从移动端跨平台开发入门到精通,如果你也喜欢关注APP、小程序、公众号、H5等等应用的开发,可以持续关注后续更新,避免错过宝贵的知识分享。
重点提醒: AI编程盛行的今天,百花齐放,要想从普通人脱颖而出,比较好的技术功底始终会先人一步,比其他普通人更容易做出精彩实用的产品,不管是用来作为工作技能、兴趣爱好、解决生活中的数字化工作也好,都是不错的一门技能,我们是脚踏实地的工程师,与其他AI吹不同,我看到的AI跟优秀的工程师还是有很大差距,AI作为工具是很好的,但是要想完全替代工程师,是绝对不可能的。只是未来的工工程师的身份会发生改变,人类协同AI进行设计、开发、交互、部署、运营等等环节都大有可为,但作为工程师,以后的要求会更加侧重于决策和指导AI进行应用设计和开发,这样无疑是对软件从业者的职业技能和工程思维的更高要求。
结论: 因此,我们不是不需要学习技术,而是更应该专研技术,拥有把控全局的架构设计思维才能在AI盛行的未来有立足之地。
言归正传,咱们今天继续来聊一聊移动端跨平台开发技术uniapp的应用声明周期详解!
我会用最糙的大白话,带你从0到1掌握UniApp的生命周期,顺便对比一下Vue3的生命周期,让你在面试、写代码以及配合AI编程review代码时都能稳如老狗,扫平一切障碍。
一、生命周期到底是个啥?
咱们可以把一个页面(或组件)想象成一个人,生命周期就是这个人的一生:出生 → 成长 → 干活 → 死亡
在代码里,就是:创建 → 挂载 → 更新 → 销毁
每个阶段框架都会给你一个钩子函数,让你可以插入自己的代码。比如出生时起个名字(接收参数),干活时刷新数据(每次显示),死亡时打扫卫生(清理定时器)。
二、UniApp 的“两套”生命周期,千万别搞混!
UniApp 因为是跨端框架(小程序+H5+App),所以它拥有两套生命周期:
-
应用生命周期 – 整个APP的启动、显示、隐藏
-
页面生命周期 – 每个页面的加载、显示、渲染完成、隐藏、卸载
注意:小程序端没有传统Web里的DOM/BOM,所以Vue的
mounted在某些端可能不会按你想的那样执行,这时候就要靠UniApp的页面生命周期了。
三、UniApp 核心生命周期详解

1️⃣ 应用生命周期(写在 App.vue 里)
// App.vue<scriptsetup>import { onLaunch, onShow, onHide } from'@dcloudio/uni-app'onLaunch(() => {console.log('App 初始化完成')// 业务:获取用户登录状态,检查更新})onShow(() => {console.log('App 进入前台')// 业务:重置倒计时,刷新全局数据})onHide(() => {console.log('App 进入后台')// 业务:保存草稿,暂停视频播放})</script>
应用场景:
-
onLaunch:只执行一次,适合检查登录态、获取系统信息、预加载资源 -
onShow:每次从后台切回前台都触发,适合刷新首页数据、恢复轮播图自动播放 -
onHide:App挂起或切到后台,适合暂停音乐、保存未提交的表单
2️⃣ 页面生命周期(写在 pages/ 下的 .vue 文件里)

<scriptsetup>import { onLoad, onShow, onReady, onHide, onUnload } from'@dcloudio/uni-app'// 页面加载,只一次,能拿到参数onLoad((options) => {console.log('页面加载,参数:', options)// 业务:根据URL参数请求详情数据getDetail(options.id)})// 页面显示,每次进入页面都会触发onShow(() => {console.log('页面显示')// 业务:刷新购物车角标,恢复定时器})// 页面首次渲染完成,可操作DOM(H5/App)onReady(() => {console.log('页面渲染完成')// 业务:获取元素宽高,初始化图表})// 页面隐藏(切入后台/跳转其他页面)onHide(() => {console.log('页面隐藏')// 业务:暂停视频播放,保存表单草稿})// 页面卸载(关闭)onUnload(() => {console.log('页面卸载')// 业务:清理定时器,取消网络请求})</script>
记忆口诀:Load拿参数,Show做刷新,Ready找元素,Hide暂停活,Unload全清空。
四、Vue3 的生命周期(老本行,但小心跨端坑!)

Vue3 的生命周期主要在组件里用,写法是 setup + onXxx。
<scriptsetup>import { ref, onMounted, onBeforeUnmount, onUpdated } from'vue'constcount=ref(0)onMounted(() => {console.log('组件挂载到DOM')// 业务:发请求,设置定时器})onUpdated(() => {console.log('组件更新')// 业务:监听数据变化,同步状态})onBeforeUnmount(() => {console.log('组件卸载前')// 业务:移除监听器,销毁echarts实例})</script>
业务场景:
-
onMounted:H5端 操作DOM,初始化非原生UI库(如ECharts) -
onBeforeUnmount:清理组件专属的定时器、事件监听 -
onUpdated:谨慎使用,容易死循环,除非你知道自己在干啥
五、UniApp vs Vue3 生命周期——到底有什么区别?怎么选?
| 场景 | 用谁? | 为什么? |
|---|---|---|
| 页面加载时请求数据 | UniApp的onLoad |
小程序端没有mounted,onLoad是页面级别的,参数也在这里传 |
| 获取页面元素高度 | UniApp的onReady |
onReady保证DOM已渲染,H5/App/小程序都有效 |
| 每次进入页面刷新数据 | UniApp的onShow |
返回上一页再回来,需要刷新;Vue的mounted只跑一次 |
| 组件内操作DOM | Vue3的onMounted |
如果你写的是通用组件,不在pages目录下,就用Vue的生命周期 |
| 清理定时器 | 对应环境的钩子 | 页面级用onUnload,组件级用onBeforeUnmount |
一句话总结:
-
页面级(.vue在pages里)用 UniApp 页面生命周期
-
组件级(components目录里)用 Vue3 组件生命周期
-
混合使用是可以的,但不要搞乱职责。
六、血泪教训:常见错误及解决方案(避坑指南)
❌ 错误1:在 onLoad 里用 uni.createSelectorQuery() 获取元素宽高
现象:在小程序里拿不到元素,返回 null 或 0。原因:onLoad 时页面还没渲染,DOM不存在。✅ 解决方案:放到 onReady 里。
// 错误onLoad(() => {uni.createSelectorQuery().select('#box').boundingClientRect(rect=> {console.log(rect) // 很可能 null }).exec()})// 正确onReady(() => {uni.createSelectorQuery().select('#box').boundingClientRect(rect=> {console.log(rect.width) // 稳了 }).exec()})
❌ 错误2:在 UniApp 页面里只用 onMounted 代替 onLoad/onShow
现象:小程序端 onMounted 确实执行,但页面返回时不会再执行,导致数据不刷新。原因:onMounted 是组件生命周期,页面卸载再进入才会重新挂载,而小程序很多场景是“页面隐藏/显示”。✅ 解决方案:用 onShow 处理每次可见时的刷新,用 onLoad 处理一次性加载。
// 页面从列表页返回详情页,详情页希望刷新评论数onShow(() => {getComments() // 每次显示都重新拉取})
❌ 错误3:定时器只创建,不销毁
现象:页面来回切换,定时器越来越多,性能下降甚至卡死。原因:在 onLoad 或 onMounted 里 setInterval,但没在 onUnload/onBeforeUnmount 里 clearInterval。✅ 解决方案:成对出现,必须清理。
lettimeronLoad(() => {timer=setInterval(() => {console.log('tick') }, 1000)})onUnload(() => {if (timer) clearInterval(timer)})
❌ 错误4:在 App.vue 的 onLaunch 里跳转页面
现象:有时候跳转成功,有时候报错 can't navigate at app launch。原因:onLaunch 时应用还没完全初始化完成,部分端(小程序)不允许立即导航。✅ 解决方案:加一点延迟,或者改用 onShow。
// 不推荐onLaunch(() => {uni.navigateTo({ url: '/pages/index' }) // 可能失败})// 推荐onLaunch(() => {setTimeout(() => {uni.navigateTo({ url: '/pages/index' }) }, 100) // 延迟100ms,给框架一点时间})
❌ 错误5:把 onShow 当成 onLoad,重复请求数据
现象:每次页面显示都重复请求不需要刷新的数据(比如用户基本信息)。原因:onShow 执行频率高,不应放置只执行一次的请求。✅ 解决方案:用标志位控制,或把不变的数据放到 onLoad。
letisFirstLoad=trueonShow(() => {if (isFirstLoad) {isFirstLoad=falsereturn }// 只刷新评论列表,不重新拉取用户信息getCommentList()})
七、终极对比表:UniApp 页面生命周期 vs Vue3 组件生命周期
| 时机 | UniApp 页面钩子 | Vue3 组件钩子 | 适用说明 |
|---|---|---|---|
| 组件/页面 创建前 | 无 | beforeCreate |
几乎不用,setup 已覆盖 |
| 组件/页面 创建后 | onLoad |
created (setup代替) |
UniApp 拿路由参数,Vue3 初始化数据 |
| DOM 挂载前 | 无 | onBeforeMount |
极少用 |
| DOM 挂载后 | onReady |
onMounted |
操作DOM、初始化第三方库 |
| 数据更新前 | 无 | onBeforeUpdate |
细粒度控制 |
| 数据更新后 | 无 | onUpdated |
依赖数据变化的DOM操作 |
| 页面/组件 显示 | onShow |
无 | UniApp特有,每次可见 |
| 页面/组件 隐藏 | onHide |
无 | UniApp特有,切后台/跳转 |
| 页面/组件 卸载前 | onUnload |
onBeforeUnmount |
清理工作 |
八、小练习:判断以下场景该用哪个生命周期?
-
H5端:页面加载时调用百度统计,记录PV。→
onLoad(只要一次) -
小程序端:用户从A页面跳到B页面,返回A页面时,A页面的滚动位置需要恢复。→
onShow里读取缓存并调用pageScrollTo -
全局组件:倒计时组件,在组件销毁时必须清除定时器。→ Vue3
onBeforeUnmount -
App端:首页轮播图自动播放,但用户滑动到其他页面后要暂停,回来继续。→
onShow开始播放,onHide暂停播放
九、教学小技巧——怎么跟新人讲清楚?
我是这么教的:
-
画人生阶段图:出生(Load)、第一次上台(Ready)、每次观众看到你(Show)、下台休息(Hide)、毕业离校(Unload)。
-
把代码注释写成“要干的事”:直接在钩子函数里写中文注释,比如
// 1.拿参数 2.请求商品详情。 -
故意写错演示:故意在
onLoad里用选择器,然后在onReady里纠正,印象特别深刻。 -
强调“谁的孩子谁负责”:页面的生命周期管页面,组件的生命周期管组件,不要越界。
十、写在最后
生命周期就像一把瑞士军刀,用对了事半功倍,用错了 debug 到秃头。记住三个原则:
-
页面级:用 UniApp 的
onLoad/Show/Ready/Hide/Unload -
组件级:用 Vue3 的
onMounted/onBeforeUnmount等 -
成对清理:定时器、监听器、长连接,在哪创建就在哪销毁
记忆口诀
-
App 三兄弟:启动
Launch,显Show,隐Hide -
页面五连:加载
Load,出现Show,就绪Ready,离开Hide,卸载Unload -
Vue3 组件:挂载
Mounted,更新Updated,卸载前BeforeUnmount
好了,今天先唠到这儿。去把你的项目生命周期整理一遍,看看有没有滥用或遗漏的地方。遇到问题随时回来翻这篇笔记,或者直接来敲我~
加油,未来的全栈大佬!💪如果你也对移动端跨端开发感兴趣,关注我,后续还有更多优质文章分享!
往期相关文章推荐


夜雨聆风
