onBackPress是uni-app中唯一可靠的跨平台页面级返回拦截入口,需在页面中显式return true阻断并手动控制navigateBack;H5需降级用history.back();全局退出逻辑应放App.vue中条件编译处理。
onBackPress 是唯一可靠的页面级拦截入口
在 uni-app 中,真正能统一拦截安卓物理返回键、导航栏左上角返回按钮的,只有 onbackpress 这个页面生命周期函数。它不是可选方案,而是官方唯一支持的跨平台(app/h5/小程序)标准接口。
常见错误是试图在组件里监听或用 plus.key.addEventListener 单独处理——前者不生效(onBackPress 不支持写在自定义组件中),后者仅限 App 端且容易和页面逻辑脱节,导致多次绑定、内存泄漏或拦截失效。
-
onBackPress的参数options.from只有两个值:"backbutton"(物理键/导航栏按钮)、"navigateBack"(JS 主动调用uni.navigateBack) - 必须显式
return true才会阻止默认返回;不返回、返回false或其它值,都会立刻执行原生跳转 - H5 平台下,浏览器地址栏的「后退」按钮和手势返回不触发
onBackPress,这是平台限制,无法绕过
拦截后弹确认框,但别让页面“先溜了”
很多人写完 uni.showModal 就直接 return true,结果用户还没点确定或取消,页面已经退回上一页——这是因为 showModal 是异步的,onBackPress 同步执行完就放行了。
正确做法是:先阻断返回(return true),再弹窗;用户点击确认后再手动调用 uni.navigateBack;点击取消则什么都不做,保持当前页。
onBackPress(options) {
if (options.from === 'backbutton') {
uni.showModal({
title: '提示',
content: '数据未保存,确定离开?',
success: (res) => {
if (res.confirm) {
uni.navigateBack({ delta: 1 });
}
// res.cancel 时什么也不做
}
});
return true; // ⚠️ 关键:立刻拦截,不等弹窗回调
}
}
多端兼容要单独处理 H5 刷新后的页面栈丢失
H5 页面刷新后,getCurrentPages() 返回空数组,此时 uni.navigateBack() 会静默失败,用户点返回键毫无反应。这不是 bug,是浏览器历史机制决定的。
解决方案不是强行补栈,而是降级使用浏览器原生能力:history.back()。
- 判断是否为 H5 平台:
uni.getSystemInfoSync().platform === 'h5' - 检查页面栈长度:
getCurrentPages().length <= 1 - 两者同时满足时,改用
history.back(),它不依赖 uni-app 栈,只操作浏览器 history
注意:history.back() 在非 H5 平台无效,必须包裹条件判断,否则 App 端会报错。
全局拦截(如退出应用)只能放在 App.vue 里
如果需求是“双击返回键退出 App”,就不能写在普通页面,得在 App.vue 的 onLaunch 或 onShow 中用 plus.key.addEventListener('backbutton', ...)。
这个 API 仅在 APP-PLUS 编译环境下有效,H5 和小程序完全不识别。而且它监听的是整个 App 的物理键,和页面无关,所以适合做全局行为(比如首页双击退出、后台运行提示)。
- 务必加
// #ifdef APP-PLUS条件编译,避免其他平台报错 - 不要在多个页面重复绑定,否则一次按键触发多次回调
- 退出逻辑推荐用
plus.runtime.quit(),比uni.navigateBack更彻底
复杂点在于:页面栈状态、是否首页、是否正在加载……这些判断得你自己维护,uni-app 不提供现成钩子。别指望一个函数搞定所有场景。

















