UniApp 路由导航守
大家平时做 Vue 项目,路由守卫基本都是标配:beforeEach 一写,白名单、token 校验、跳转拦截一气呵成。
但换到 UniApp 就会发现一个问题:没有 Vue-Router,也没有 beforeEach。
很多人刚上手都会懵:路由守卫到底怎么写?
其实 UniApp 有自己的方案,就是官方提供的 拦截器(interceptor),今天就把完整可落地、直接复制粘贴的路由守卫给你们。
Vue 里是这样写的
javascript
router.beforeEach((to, from, next) => {
if (to.path === '/login') return next()
const token = sessionStorage.getItem('token')
if (!token) return next('/login')
next()
})
逻辑很简单:
- 白名单直接过
- 没 token 跳登录
- 有 token 正常跳转
但 UniApp 不这套,它的页面跳转全靠:
- uni.navigateTo
- uni.redirectTo
- uni.reLaunch
- uni.switchTab
所以思路也很直接:把这几个 API 全部拦截,自己做校验。
UniApp 路由守卫核心:拦截器
官方文档里其实写得很清楚:
uni.addInterceptor 可以拦截几乎所有 uni 开头的 API,包括路由、请求、扫码、支付等等。
路由守卫,本质就是:
拦截路由跳转 → 判断权限 → 放行 / 拦截跳登录
拦截器最重要的就是一个方法:
invoke(args)
- return true = 放行
- return false = 拦截,不执行原来的跳转
懂这个,整个路由守卫就通了。
直接上代码:utils/interceptor.js
javascript
// 全局路由拦截器(路由守卫)
// 在 App.vue onLaunch 中调用一次即可
// 白名单:不需要登录就能访问的页面
const whiteList = new Set([
'/pages/login/login',
// '/pages/register/register', 想加就加
])
// 核心校验逻辑
function checkAuth(url) {
// 截取纯路径,忽略 ? 参数
const path = url.split('?')[0]
// 白名单直接放行
if (whiteList.has(path)) {
return true
}
// 校验 token
const token = uni.getStorageSync('token')
return !!token
}
// 拦截器配置
const routeInterceptor = {
invoke(args) {
console.log('即将跳转:', args.url)
// 校验通过,正常跳转
if (checkAuth(args.url)) {
return true
}
// 未登录 → 跳登录,并把原来要跳的地址带上
uni.redirectTo({
url: `/pages/login/login?redirect=${encodeURIComponent(args.url)}`
})
// 拦截本次路由跳转
return false
}
}
// 注册所有路由拦截
export function initRouteGuard() {
uni.addInterceptor('navigateTo', routeInterceptor)
uni.addInterceptor('redirectTo', routeInterceptor)
uni.addInterceptor('reLaunch', routeInterceptor)
uni.addInterceptor('switchTab', routeInterceptor)
}
在 App.vue 中启用(非常关键)
为什么必须写在 onLaunch?
因为:
拦截器必须在任何页面跳转之前就注册好
onLaunch 是应用启动最早的生命周期,只执行一次,最适合干这事。
vue
<script>
import { initRouteGuard } from '@/utils/interceptor.js'
export default {
onLaunch() {
// 启动路由守卫
initRouteGuard()
},
onShow() {},
onHide() {}
}
</script>
登录成功后如何"回跳原来页面"
拦截时我们拼了一个 redirect 参数:
/login?redirect=xxx
登录成功后这样跳回去就行:
javascript
async function login() {
// 登录请求...
const token = res.data.token
uni.setStorageSync('token', token)
// 获取当前页面实例
const pages = getCurrentPages()
const current = pages[pages.length - 1]
const redirect = current.options.redirect
if (redirect) {
// 跳回原来想访问的页面
uni.redirectTo({
url: decodeURIComponent(redirect)
})
} else {
// 默认跳首页或 tabBar
uni.switchTab({
url: '/pages/home/home'
})
}
}
一些实用小细节
-
tabBar 页面也能拦截
switchTab 已经包含在拦截里,没 token 照样跳登录。
-
路径一定要写完整
/pages/login/login别写错,不然白名单不生效。 -
navigateBack 一般不用拦截
返回上一页通常不需要权限,除非你有特殊场景。
-
可扩展权限控制
想加角色、验过期、验状态,直接在
checkAuth里加逻辑就行,非常灵活。
总结
- UniApp 没有 beforeEach,但能用
uni.addInterceptor实现一模一样的效果 - 拦截 navigateTo / redirectTo / reLaunch / switchTab 四个 API 就够覆盖所有路由
- 白名单 + token 校验 = 最常用路由守卫
- 必须在 App.vue onLaunch 里初始化,否则不生效
- 代码直接复制,改改页面路径就能上线
这套写法我在好几个 UniApp 项目里都在用,H5、小程序、App 全端稳定,没坑。