uni.navigateTo前必须确保倒计时真正结束、状态干净,否则易失败或残留遮罩;需用setTimeout递归校验时间、清理uni.showLoading等遮罩、加状态锁防重复跳转,并在onHide/onUnload中清除定时器。

uni.navigateTo 前必须确保倒计时已真正结束、页面状态干净,否则跳转可能失败或残留 UI 遮罩。
倒计时逻辑别用 setInterval 直接减秒
常见错误是写个 setInterval 每秒 count--,然后 if (count 就跳转——这在小程序后台会被暂停,切回来时 <code>count 还卡在 2,但实际已超时 5 分钟。
- 正确做法:服务端下发截止时间戳(如
expireAt: 1749819240000),前端始终用Date.now() >= this.expireAt判断是否该跳转 - UI 层倒计时展示可用
requestAnimationFrame,每次帧中重算剩余毫秒:const remainMs = Math.max(0, this.expireAt - Date.now()) - 不要把
count存在data里直接绑定;改用computed或watch响应式监听remainMs,避免频繁setData
uni.navigateTo 调用前必须清理干扰层
跳转卡住、黑屏、白屏,90% 是因为没关掉之前弹出的 uni.showLoading、uni.showToast 或 uni.showModal。
-
uni.showLoading({ mask: true })后,必须显式调用uni.hideLoading(),不能依赖跳转自动关闭 -
uni.showToast和uni.showModal的遮罩层(mask)与路由无关,跳转前务必手动清除 - 如果用了自定义弹窗组件(比如倒计时浮层),要在跳转前
this.$refs.popup?.hide?.()或设visible = false
跳转触发时机要防重复 + 防穿透
用户快速点击“跳过”或倒计时期间反复进出页面,容易导致多次跳转、白屏或路由栈混乱。
- 加一个状态锁:
isNavigating: false,跳转前判断并设为true,防止重复执行 - “跳过”按钮必须加
@click.stop.prevent或catchtouchmove,尤其 iOS 上不加会触发底层页面滚动,露出 tabbar - 在
onUnload或onHide中清理定时器:clearTimeout(this.timerId)、cancelAnimationFrame(this.rafId),否则内存泄漏
多端兼容:APP 和小程序行为差异必须处理
Web 端倒计时准,但小程序和 APP 后台冻结 JS,不能靠“每秒减一”逻辑驱动跳转。
- 微信/支付宝小程序:页面
onHide后所有定时器冻结,onShow时必须重新校验Date.now() >= expireAt - iOS App 后台最多运行 30 秒,Android 行为不一,一律按“只校验不计时”原则设计
- 不要用 uView 的
<uni-countdown></uni-countdown>组件做跳转依据——它底层是setInterval,只适合静态展示
真实跳转动作发生时,往往不是“时间到了”,而是“校验通过 + 状态就绪 + 遮罩已清”。最容易被忽略的是:服务端时间戳没转毫秒、uni.hideLoading 漏调、以及 iOS 上按钮没加 catchtouchmove 导致跳转后还能滑动露出底色。











