UniApp 路由导航守卫

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 参数:

ini 复制代码
/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'
    })
  }
}

一些实用小细节

  1. tabBar 页面也能拦截 switchTab 已经包含在拦截里,没 token 照样跳登录。

  2. 路径一定要写完整 /pages/login/login 别写错,不然白名单不生效。

  3. navigateBack 一般不用拦截 返回上一页通常不需要权限,除非你有特殊场景。

  4. 可扩展权限控制 想加角色、验过期、验状态,直接在 checkAuth 里加逻辑就行,非常灵活。


总结

  • UniApp 没有 beforeEach,但能用 uni.addInterceptor 实现一模一样的效果
  • 拦截 navigateTo / redirectTo / reLaunch / switchTab 四个 API 就够覆盖所有路由
  • 白名单 + token 校验 = 最常用路由守卫
  • 必须在 App.vue onLaunch 里初始化,否则不生效
  • 代码直接复制,改改页面路径就能上线

这套写法我在好几个 UniApp 项目里都在用,H5、小程序、App 全端稳定,没坑。

相关推荐
星空7 小时前
Map<String, String>`Map`是接口,不能直接 new
java·前端·算法
开开心心就好7 小时前
低年级识字练笔顺工具,电脑和安卓端都能用
前端·javascript·网络·安全·scala·erlang·语音识别
杨利杰YJlio8 小时前
ITSK PE 26U5 测试版解读:组件完善、VMD 修复与服务器支持边界
前端·javascript·后端
志尊宝8 小时前
Vue3 零基础每日笔记(021):class 与 style 动态绑定——对象、数组、三元表达式写法汇总
前端·vue.js·笔记·前端框架·html5
夏幻灵8 小时前
Vue / React 列表渲染中的 key:为什么没有 key,Checkbox 可能“对号跑错”?
前端·javascript·vue.js
YWL8 小时前
vue-time-axis-plus进阶:双进度条+跨空白续播+播放指针,打造专业级监控回放体验
前端·javascript·vue·时间轴
mmsx8 小时前
MapLibre 实战 09|Bug 单写着"地图被风刮走了":一个瓦片源工厂,是三个线上事故换来的
android·前端·开源
不羁的木木8 小时前
给鸿蒙 App 增加打开外部网页能力 —— flutter_web_browser 的鸿蒙使用指南
前端·flutter·harmonyos
广州山泉婚姻8 小时前
微服务时代,前后端分离架构该怎样高效协同?
前端·后端
EatFan8 小时前
多租户系统到底怎么设计?从 tenant_id 到 JWT 租户隔离的真实实践
前端·后端·全栈·多租户