H5刷新后Token丢失是因为onLaunch不触发,需在onShow中调用restoreToken恢复;该函数应读取storage中的token并注入请求拦截器、全局状态,且登录成功后须立即持久化并执行restoreToken。

刷新后 Token 丢失,不是没存进去,而是没在正确时机取出来用 —— uni.getStorageSync('token') 确实有值,但请求拦截器、全局状态、路由守卫都没拿到它。
为什么 onLaunch 不足以覆盖 H5 刷新场景
H5 的 onLaunch 只在首次加载时触发;用户手动刷新、第三方回调(如人脸核身完成页)或浏览器标签页重激活,都会跳过 onLaunch,直接走 onShow。此时若没重新读取并注入 Token,所有后续请求都带空 Authorization 头,必然 401。
-
onLaunch适合初始化,但不能替代每次可见时的状态同步 -
onShow是 H5 刷新后唯一可靠入口,必须在此恢复 Token - 避免在
main.js或store/index.js中直接调用uni.getStorageSync—— H5 端此时uniAPI 尚未就绪,会返回undefined
App.vue 中统一 restoreToken 的实操写法
把 Token 恢复逻辑抽成独立函数,在 onLaunch 和 onShow 里都调用它:
function restoreToken() {
const token = uni.getStorageSync('token')
if (token) {
// 注入请求拦截器(适配 uni-app 3.x / 2.x)
uni.addInterceptor('request', {
invoke(args) {
args.header = {
...args.header,
Authorization: `Bearer ${token}`
}
}
})
// 同步到全局状态(如 Pinia 或 uni.$u.store)
if (typeof uni.$u?.store?.setToken === 'function') {
uni.$u.store.setToken(token)
}
}
}
- 务必检查
token是否存在再注入,避免空字符串污染请求头 - 拦截器需在每次
restoreToken调用时重新注册,否则刷新后拦截器失效 - 若用 Pinia,确保 store 在
onLaunch后才创建,否则uni.$u.store可能为undefined
登录成功后必须立即持久化 + 触发 restore
仅调用 uni.setStorageSync('token', xxx) 不够,还要立刻执行一次 restoreToken(),否则当前页面的请求仍无 Token。
- 登录接口成功回调里:先存,再恢复,再跳转
- 不要依赖组件内
onLoad或mounted去读取 Token —— 页面可能已发出请求,拦截器还没挂上 - 敏感操作(如支付、核身)前,建议加一层运行时校验:
if (!uni.getStorageSync('token')) { uni.navigateTo({ url: '/pages/login/login' }) }
容易被忽略的兼容性细节
第三方回调页(如腾讯云核身)常强制刷新且带 query 参数,此时 onShow 会触发,但 options 不可用 —— 它只在 onLoad 里有。所以 Token 恢复逻辑绝不能依赖 options,必须纯靠 uni.getStorageSync。
- 部分安卓 WebView 对
localStorage有异步写入延迟,setStorageSync后立即getStorageSync可能拿不到最新值;可加setTimeout微调,但更稳妥是统一走同步存储 + 主动恢复 - 微信内置浏览器对
history.state有特殊处理,但不影响uni.getStorageSync,无需额外兼容 - 上线前必须实测「核身回调 → 刷新 → 返回首页 → 点击个人中心」全流程,确认 Token 未丢失、请求未 401


















