uni.addinterceptor是目前最可靠、侵入性最小的全局路由守卫实现方式,需拦截navigateto、redirectto、relaunch、switchtab四个api,配合路径标准化、token严格校验及早期初始化。

uni.addInterceptor 是目前最可靠、侵入性最小的全局路由守卫实现方式。它不依赖第三方库,不改写原始 API,也不强制团队约定调用规范,能真正覆盖所有跳转入口(包括 uni.navigateTo、uni.redirectTo、uni.reLaunch、uni.switchTab)。
uni.addInterceptor 必须拦截的四个 API
UniApp 的页面跳转行为分散在多个 API 中,只拦截 uni.navigateTo 是不够的:
-
uni.navigateTo:普通页面跳转(带栈) -
uni.redirectTo:替换当前页(无栈) -
uni.reLaunch:清空栈后跳转(常用于登录后回首页) -
uni.switchTab:仅限 tabBar 页面,且会清除非 tab 页
每个都必须单独加拦截器,漏掉任意一个,守卫逻辑就可能被绕过:
uni.addInterceptor('navigateTo', { invoke: checkAuth })
uni.addInterceptor('redirectTo', { invoke: checkAuth })
uni.addInterceptor('reLaunch', { invoke: checkAuth })
uni.addInterceptor('switchTab', { invoke: checkAuth })
invoke 是唯一可执行同步校验的钩子;不要用 success 或 fail —— 那是跳转之后才触发的,拦不住。
白名单路径匹配要剥离 query 参数
很多同学直接拿 args.url 做白名单比对,结果 /pages/login/login?from=pay 被误判为非白名单,导致登录页也跳不过去:
- 错误写法:
routeConfig.whiteList.has(args.url) - 正确写法:
const path = args.url.split('?')[0]; routeConfig.whiteList.has(path)
另外注意:
-
uni.switchTab的args.url不带pages/前缀(如传入'/tabBar/mine'),而白名单里通常写的是完整路径,需统一处理 - 小程序端
args.url可能是相对路径(如'../login/login'),建议在比对前 normalize 成标准绝对路径(可用uni.getStorageSync('currentPage')辅助推导,或直接限定白名单只收绝对路径)
Token 校验不能只看是否存在
uni.getStorageSync(routeConfig.tokenKey) 返回 null、undefined、空字符串、甚至 JSON 字符串(如果之前存的是 JSON.stringify({ token: 'xxx' }))都算“无效”:
- 必须显式判断类型和长度:
typeof token === 'string' && token.trim().length > 0 - 如果后端返回的是对象结构,记得先
JSON.parse()再取字段,否则token.exp会报错 - 过期检查别写死:
Date.now() > exp * 1000,别漏乘 1000
跳转逻辑也要小心:
- 拦截后调用
uni.navigateTo({ url: routeConfig.loginPage })是安全的(不会再次触发拦截器) - 但若在
invoke里直接return,跳转就静默失败,用户无感知;务必配合uni.showToast或uni.showModal提示
守卫初始化时机很关键
必须在 App 启动早期注册拦截器,否则冷启动时第一次跳转可能逃逸:
- ✅ 正确位置:在
App.vue的onLaunch或onShow中调用初始化函数 - ❌ 错误位置:放在某个页面的
onLoad里,或异步懒加载的工具模块中
还要注意 H5 端的特殊性:
- H5 使用的是浏览器 history 跳转,
uni.addInterceptor不生效 - 如果需要 H5 兼容,得额外监听
popstate或结合router.beforeEach(需引入@gowiny/uni-router或uni-simple-router)
真正的难点不在写逻辑,而在于——你永远没法 100% 确保所有跳转都走这四条路。比如原生插件、自定义组件内硬编码的 location.href、或者 web-view 里的链接,守卫完全管不到。










