双击退出逻辑必须写在app.vue中,通过onbackpress全局拦截并立即return true,用this.lastbacktime+settimeout清零实现2秒防抖,仅首页(栈深为1)生效,app-plus平台调用plus.runtime.quit()。

onBackPress 必须写在 App.vue 里才能生效
双击退出逻辑不是页面级行为,不能放在 pages/index/index.vue 或任何业务组件中。用户从子页返回首页后按两次返回键,如果逻辑只在首页定义,第二次触发时已不在该页面实例内,直接失效。只有 App.vue 的生命周期能贯穿整个 App 运行过程,且 onBackPress 在这里声明才具备全局拦截能力。
时间戳判断要立刻 return true,否则默认返回先执行
这是最常踩的坑:不立即 return true,系统就会走默认逻辑——比如跳上一页或清空栈,弹窗都来不及显示。正确顺序是:
- 入口第一行就
return true - 接着取
Date.now() - 比对
this.lastBackTime间隔是否小于 2000ms - 满足则调
plus.runtime.quit();不满足则弹 toast 并结束
错误写法示例:if (res.confirm) { plus.runtime.quit(); } 后再 return true——用户还没点确认,页面已经退了。
变量必须挂载到 this 上,且用 setTimeout 清零
this.lastBackTime 必须定义在 App.vue 的 data 中,不能是函数内局部变量。清零也不能靠计数器或手动重置,得用:
setTimeout(() => {
this.lastBackTime = 0;
}, 2000)
注意必须是箭头函数,否则 this 指向错误,赋值失败。2000ms 是经验值,太短易误触,太长体验拖沓。
非首页要禁用,避免干扰正常后退
用户在表单页、详情页等子页按返回键,理应后退至上一页,而不是触发退出逻辑。可用 getCurrentPages().length === 1 判断当前是否在栈底(即首页)。iOS 和 H5 不支持真退出,plus.runtime.quit() 要用 // #ifdef APP-PLUS 包裹,否则编译报错。
真正容易被忽略的是:很多项目把双击逻辑写在首页,却没加栈深判断,结果用户从二级页返回首页后,第一次返回就卡住——因为首页的 onBackPress 拦截了所有来源,包括 uni.navigateBack() 触发的返回,导致无法退栈。











