onBackPress 是拦截返回键并弹确认框的唯一可靠入口,需返回 true 阻止默认行为、加 isConfirming 防重复弹窗,onUnload 中无法弹窗属平台限制,H5 需额外处理,tabBar 切页须用 getCurrentPages 结合 onShow 检测。

uni-app 中 onBackPress 拦截返回键并弹确认框
App 端物理返回键默认直接退出页面,想提示“是否离开”必须主动拦截。关键不是监听页面卸载,而是捕获 onBackPress 事件并返回 true 阻止默认行为。
常见错误是只写 uni.showModal 却没在回调里控制导航逻辑,导致弹窗一出来就已跳转或退出。
-
onBackPress在 App(Android/iOS)和小程序中均有效,但 H5 不支持该钩子,需额外处理键盘后退或浏览器历史栈 - 必须显式返回
true才能阻止默认返回;返回false或不返回,系统仍会执行原生返回逻辑 - 避免重复弹窗:加个
isConfirming标志位,防止用户连按多次触发多个弹窗 - 示例代码片段:
export default {
data() {
return { isConfirming: false }
},
onBackPress() {
if (this.isConfirming) return true
this.isConfirming = true
uni.showModal({
title: '提示',
content: '确定要离开当前页面吗?',
success: (res) => {
if (res.confirm) {
// 允许返回:这里可手动调用 uni.navigateBack()
uni.navigateBack()
} else {
// 取消,什么也不做
}
},
complete: () => {
this.isConfirming = false
}
})
return true // 阻止默认行为
}
}
页面卸载前(onUnload)无法可靠弹窗的原因
onUnload 是页面即将销毁的信号,此时视图层已冻结,uni.showModal 在多数平台(尤其是 App)会静默失败或直接报错 Modal is not allowed in onUnload,属于平台限制,不是代码问题。
所以别试图在 onUnload 里做确认,它只适合清理定时器、取消请求、解绑事件等无 UI 操作。
- 微信小程序中,
onUnload触发时页面 DOM 已被移除,弹窗无宿主容器 - App 端(plus)虽部分支持,但行为不稳定,且无法响应用户点击,容易卡死
- 真正需要“离开前确认”的场景,唯一可控入口就是
onBackPress(返回键)和自定义返回按钮的 click 事件
如何拦截 tabBar 或顶部返回按钮的离开行为
顶部导航栏的返回按钮(navigationStyle: custom 时自己写的)或 tabBar 切页,都不走 onBackPress,得靠页面栈 + onShow + getCurrentPages 主动识别“非预期离开”。
比如用户从订单页点 Tab 切到首页,订单页触发 onHide,但你无法在此刻弹窗——只能提前在订单页监听 onShow,检查上一页是不是 tabBar 页面,再决定是否置灰操作或提示草稿未保存。
- 用
getCurrentPages()获取当前栈,判断pages[pages.length - 2]?.route是否属于 tabBar 页面路径(如pages/index/index) - 若检测到是从 tabBar 来的,说明用户可能误操作,可在页面顶部加一个轻量提示条(非 modal),避免中断流程
- 对 tabBar 页面本身,可在
onTabItemTap中做防抖 + 确认,但注意:该钩子不传目标页实例,无法 cancel 切页,只能uni.showToast提示后由用户重试
为什么 onShow 不能替代离开确认逻辑
onShow 是“页面显示时”触发,不是“页面离开前”。把它当离开钩子用,本质是倒推行为——比如用户从 A 页返回 B 页,B 页 onShow 被触发,这时你能知道“刚回来”,但无法干预 A 页是否已销毁或用户是否点了返回键。
真正需要阻断离开动作的,只有两个时机:用户按下返回键(onBackPress)、用户点击自定义返回按钮(绑定 click 后手动 showModal 并控制后续逻辑)。
复杂点在于:App 和小程序对 onBackPress 的兼容细节不同,iOS 物理键可能被系统接管,部分低端 Android 设备会忽略返回值;所以生产环境务必真机测试,别只信模拟器表现。










