onBackPress 中仅 return true 且 options.from === 'backbutton' 时才应拦截物理返回键;双击退出逻辑须置于 App.vue 中,iOS 侧滑需在 pages.json 中设 "popGesture": "close" 才触发 onBackPress。

onBackPress 里 return true 才能拦截,但别拦死所有来源
在 App 端(Android),物理返回键的拦截必须依赖 onBackPress,且只有显式 return true 才会阻止默认行为。不返回、返回 false 或其它值,页面都会立刻退栈。
但关键陷阱是:它不区分“用户真想退出 App”和“只是想回上一页”。如果在任意页面都无差别 return true,会导致右上角菜单里的“返回”、uni.navigateBack() 调用全部失效——用户点哪都退不了。
-
options.from === 'backbutton'才代表物理键或导航栏按钮触发,这是你该干预的唯一信号 -
options.from === 'navigateBack'是 JS 主动跳转,通常不该拦截,否则可能卡死页面栈 - 不要在组件中写
onBackPress,它只在页面级(pages/xxx.vue)或App.vue中生效
双击退出 App 的逻辑必须放在 App.vue 里
页面级的 onBackPress 只影响当前页,而“退出应用”是全局行为,必须下沉到 App.vue 的生命周期中处理。
常见错误是把双击逻辑写在某个业务页里,结果切到别的页面后就失效了。正确做法是:在 App.vue 的 onLaunch 或 onShow 中监听物理键,并用时间戳判断双击间隔。
- 使用
plus.key.addEventListener('backbutton', ...)(仅 App 端有效) - 首次点击记录时间,第二次点击检查间隔是否 plus.runtime.quit()
- 务必用
if (process.env.UNI_PLATFORM === 'app-plus')条件编译包裹,否则 H5 和小程序会报错 - 不要在业务页重复绑定,避免多次监听导致退出异常
H5 平台无法拦截浏览器返回,得降级用 history.back()
onBackPress 在 H5 平台完全不触发——浏览器地址栏后退、手势返回、Alt+← 都绕过它。这不是 bug,是浏览器安全机制决定的。
所以如果你的项目要支持 H5,不能指望 onBackPress 统一处理。得单独判断平台,对 H5 降级使用原生 window.history.back()。
- 先用
uni.getSystemInfoSync().platform === 'h5'判断环境 - 再检查
history.length > 1,避免history.back()失效时白屏 - 别直接替换
uni.navigateBack(),H5 下它依赖 uni-app 页面栈,刷新后栈为空,调用即静默失败 - 注意:H5 下无法弹确认框后再执行
history.back(),因为浏览器返回是同步不可逆的
iOS 侧滑返回根本不会进 onBackPress,得关原生手势
这是最常被忽略的事实:onBackPress 完全不响应 iOS 的边缘侧滑返回手势。你测试时发现 Android 正常、iOS 没反应,不是代码问题,是系统限制。
要统一控制,只能提前在 pages.json 中关闭原生侧滑,再手动实现 touch 事件模拟返回动画——但这成本高、体验难对齐系统。
- 在对应页面的
style配置中加"popGesture": "close" - 关闭后,iOS 物理键(如果有)和导航栏按钮才会走
onBackPress - 但用户仍可通过系统级多任务手势退出 App,这部分无法拦截,也不建议强行阻止
- 微信小程序同理:侧滑返回不触发
onBackPress,且无法关闭,只能接受其行为
真正复杂的是多端行为不一致:Android 物理键可拦、iOS 侧滑拦不了、H5 浏览器返回拦不住、小程序又各有规则。别试图写一套逻辑打天下,按平台拆解、各自兜底才是稳的路子。


















