onHide是App端唯一稳定触发的进入后台信号,需轻量收尾并实时持久化关键状态;onShow是前台恢复唯一可靠入口,须校验网络、登录态并重连原生模块。

onHide 是你唯一能拿到的“进入后台”信号
uni-app 中,onHide 是 App 端(iOS/Android)唯一稳定触发的、表示应用进入后台的生命周期钩子。它会在用户按下 Home 键、切换到其他 App、锁屏等场景下执行。但它不是“退出”,更不等于进程被杀——系统可能随时回收 JS 上下文,且不会再次通知你。
常见错误是把 onHide 当作“退出前回调”来发上报或清理长连接。实际中,用户切回前台后可能几秒就 onShow 了,你报的“已退出”就是错的。
- 必须在这里做轻量级收尾:清除
setInterval/setTimeout、暂停音频/视频播放、停发心跳请求 - 关键状态(如表单草稿、播放进度)不能只靠
onHide持久化,得在变更时实时调用uni.setStorageSync - iOS 后台 JS 执行权极不可靠,
setTimeout在后台大概率被暂停(尤其 iOS 15+),别指望它能撑过 30 秒
onShow 是恢复逻辑的唯一可靠入口
onShow 是你每次切回前台后,第一个且必然触发的钩子。但它不区分“冷启动”和“热切回”——从桌面点图标进来、从微信切回来、甚至从通知栏点开,都会走它。
所以不能默认“一进前台就刷新全部数据”。真实场景里,你需要:
- 检查网络状态:
uni.getNetworkType,避免 Wi-Fi 切流量后请求失败 - 校验登录态有效性:仅
uni.getStorageSync('token')存在 ≠ 有效,建议发个轻量 API(如/auth/validate)确认 - 重连原生模块:用了定位、蓝牙、摄像头等插件的,
onShow里需手动重启,不能假设它们还在线 - 页面实例可能已被系统回收(尤其低内存 Android 机型),不要依赖上一次 Vue 实例里的 data,一切以本地存储或服务端为准
如何获取“用户离开时在哪个页面”
onHide 本身不带页面信息,但你可以结合 getCurrentPages() 主动抓取:
onHide() {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
if (currentPage) {
// 保存当前页面路径和参数,用于后续分析或上报
uni.setStorageSync('lastPage', {
route: currentPage.route,
options: currentPage.options,
timestamp: Date.now()
})
}
}
注意:getCurrentPages() 返回的是页面栈快照,不是实时监听器。它只能告诉你“进入后台那一刻,栈顶是哪个页面”,无法捕获用户中途切页但未触发 onHide 的情况。
- 不要在
onHide里发网络请求——后台 JS 可能被立即冻结,请求大概率失败或超时 - 若需上报“离开页面”,建议只存本地,下次
onShow或onLaunch时统一上传 - iOS 下
onHide触发后约 10 秒内,JS 就可能被系统静默终止,没机会执行异步回调
为什么没有 onExit 或 onTerminate?
这不是 uni-app 的缺陷,而是原生平台限制:iOS 和 Android 均未向 JS 层暴露“进程即将被杀死”的回调接口。系统决定回收时,JS 上下文直接销毁,连 onError 都来不及触发。
所以所有“模拟退出行为”的方案,本质都是补位:
- Android:可用原生插件监听
onTaskRemoved,在前台服务中执行清理(需 manifest 配置权限) - iOS:无法监听终止,但可在
onHide后发一个带时间戳的本地通知,下次onLaunch时比对间隔,若 >5 分钟,可近似认为上次是非正常退出 - 最稳妥的通用策略:所有关键状态变更即存,不押宝在“最后时刻”
真正容易被忽略的,是开发者总想等“最后一刻”再保存或上报。而现实是——你根本不知道哪一刻是最后一刻。











