onbackpress 必须写在页面级 vue 文件中,组件内无效;需在页面 onload 中验证,返回值必须为 true 才能拦截,h5 刷新后需降级使用 history.back()。

onBackPress 必须写在页面级 Vue 文件里,组件里无效
你没法在 .vue 自定义组件中监听安卓返回键或导航栏左上角按钮——onBackPress 只在页面生命周期中生效,比如 pages/detail/detail.vue。写在 components/header.vue 里完全不会触发。
常见错误是把逻辑塞进公共组件,结果调试半天发现函数压根没执行。确认位置的最简单办法:在页面 onLoad 里 console.log('page loaded'),再按返回键看 onBackPress 是否被调用。
-
onBackPress是页面级钩子,不是全局事件总线 - App 和小程序平台支持
from: 'backbutton'(物理键 + 导航栏按钮),H5 平台仅支持导航栏按钮,不响应浏览器原生返回键 - 返回值必须是
true才能拦截;false、undefined或不写 return 都会走默认跳转
拦截后弹确认框,必须立刻 return true,不能等回调
uni.showModal 是异步 API,但 onBackPress 是同步执行的。如果你写成:
onBackPress() {
uni.showModal({ content: '确定离开?' })
return true // ❌ 错误:弹窗还没出来,页面已卡住
}
用户会看到界面冻结,或者点“确定”后页面状态错乱。正确做法是立即拦截,把后续动作交给回调:
- 第一行就
return true - 在
showModal的success回调里处理跳转逻辑,比如uni.navigateBack({ delta: 1 })或uni.reLaunch - 如果用户点“取消”,什么也不做即可(不调用任何跳转)
H5 页面刷新后 onBackPress 失效,要降级用 history.back()
H5 刷新后,getCurrentPages() 返回空数组,uni.navigateBack() 会静默失败——这不是 bug,是浏览器历史栈和 uni-app 页面栈脱节导致的。
判断条件有两个,缺一不可:
uni.getSystemInfoSync().platform === 'h5'getCurrentPages().length
同时满足时,直接调用 history.back()。它不依赖 uni-app 栈,只操作浏览器 history 记录,能真实回退到上一页(哪怕那页不是 uni-app 页面)。
自定义返回按钮图标时,点击事件不能替代 onBackPress
用 navigationStyle: "custom" 隐藏原生导航栏、自己画一个返回图标(比如 <image src="/static/back.png"></image>),这只是 UI 层控制,和系统返回键完全无关。
这意味着:
- 安卓用户仍可按物理返回键,触发的是原生行为,除非你写了
onBackPress - 自定义按钮的
goBack方法建议也兼容多端:在 App 和小程序里用uni.navigateBack,H5 里 fallback 到history.back() - 不要以为加了自定义按钮就不用管
onBackPress—— 它俩解决的是不同路径的返回入口
真正健壮的方案是:自定义按钮 + onBackPress + H5 历史降级,三者并存,各自负责对应场景。最容易被忽略的是 H5 刷新后的那个空栈判断,线上经常因此出现“点返回没反应”的投诉。










