bun + vite7 的结合,孕育的 Robot Admin 【靓仔出道】(九)

Robot Admin 路由与导航系统详解

等级:进阶 | 阅读时间:9分钟

Robot Admin项目实现了一个全面的路由和导航系统,包括动态路由生成、权限控制和导航守卫。本文将帮助您理解路由系统的工作原理以及如何实现自定义路由。

路由架构概述

Robot Admin中的路由系统基于Vue Router构建,结构设计用于处理公共路由和基于用户权限动态生成的路由。系统由四个主要组件组成:

  • index.ts - 核心路由实例配置
  • publicRouter.ts - 公共路由定义
  • dynamicRouter.ts - 动态路由生成逻辑
  • permission.ts - 权限控制与导航守卫

路由配置

核心路由实例在index.ts中创建,支持哈希和历史模式,可通过环境变量配置。

javascript 复制代码
// 路由模式通过环境变量配置
const mode = import.meta.env.VITE_ROUTER_MODE as 'hash' | 'history'
 
const routerMode = {
  hash: () => createWebHashHistory(),
  history: () => createWebHistory(),
}
 
const historyCreator = routerMode[mode] || createWebHashHistory
 
const router = createRouter({
  routes,
  history: historyCreator(),
  strict: false,
  scrollBehavior: () => ({ left: 0, top: 0 }),
})

路由类型

公共路由

公共路由始终可访问,无需认证。这些路由定义在publicRouter.ts中,包括:

  • 登录页面
  • 错误页面(401, 404)
  • 用于处理未知URL的捕获所有路由
javascript 复制代码
export const publicRoutes: RouteRecordRaw[] = [
  {
    path: '/login',
    name: 'login',
    component: () => import('_views/login/index.vue'),
    meta: {
      title: '登录',
      icon: '',
      hidden: true,
      // 其他元数据...
    },
  },
  // 401, 404和其他公共路由...
]

动态路由

动态路由基于用户权限生成,在成功认证后初始化。系统使用服务器响应来构建路由结构。

路由元属性

每个路由可以包含控制其行为和在导航系统中显示方式的元数据:

属性 类型 描述
title string 在导航和页面标题中显示的路由标题
icon string 在导航菜单中显示的图标
hidden boolean 路由是否在导航菜单中隐藏
affix boolean 路由标签是否固定,不能关闭
keepAlive boolean 路由组件是否应缓存
full boolean 路由是否应全屏显示
link string 如果路由指向外部资源,则为外部链接URL

动态路由生成

系统提供工具将后端的路由定义转换为实际的Vue Router路由。

路由处理

processRoute函数将原始路由定义转换为有效的Vue Router路由:

ini 复制代码
const processRoute = (route: DynamicRoute, isChild = false): RouteRecordRaw => {
  return {
    ...route,
    path: normalizePath(route.path, isChild),
    component: resolveComponent(route.component),
    children: route.children?.map(child => processRoute(child, true)),
    meta: {
      ...route.meta,
      isLayout: route.component === 'layout',
    },
  } as RouteRecordRaw
}

组件解析

组件使用Vite的import.meta.glob功能动态解析:

typescript 复制代码
const resolveComponent = (path?: string) => {
  if (!path) return undefined
 
  // 检查预定义组件
  if (path in COMPONENTS) {
    return COMPONENTS[path as keyof typeof COMPONENTS]
  }
 
  try {
    const normalizedPath = path.startsWith('/') ? path : `/${path}`
    const viewPath = `/src/views${normalizedPath}.vue`
    const modules = import.meta.glob('@/views/**/*.vue')
 
    if (modules[viewPath]) {
      return modules[viewPath]
    }
 
    // 如果找不到组件,回退到404
    return COMPONENTS['404']
  } catch (error) {
    return COMPONENTS['404']
  }
}

初始化动态路由

initDynamicRouter函数从权限存储中获取路由数据并添加到路由器:

typescript 复制代码
export const initDynamicRouter = async (): Promise<boolean> => {
  try {
    const permissionStore = s_permissionStore()
    const { code, data: routes, msg } = await permissionStore.getAuthMenuList()
 
    if (code !== '0' || !Array.isArray(routes)) {
      throw new Error(msg || '无效的路由数据格式')
    }
 
    clearExistingRoutes(['login', '404', '401'])
 
    routes
      .map(route => processRoute(route))
      .forEach(route => router.addRoute(route))
 
    return true
  } catch (error) {
    handleRouteError(error)
    return false
  }
}

权限控制与导航守卫

导航守卫基于认证状态和用户权限控制对路由的访问。

主导航守卫

permission.ts中的主导航守卫处理多种情况:

  • 未认证用户重定向到登录页面(白名单路由除外)
  • 已认证用户访问登录页面重定向到主页
  • 如果尚未加载,初始化动态路由
  • 根据路由元数据设置页面标题
vbnet 复制代码
router.beforeEach(
  async (to: RouteLocationNormalized): Promise<string | boolean> => {
    nprogress.start()
 
    try {
      const userStore = s_userStore()
      const { token } = userStore
      const { authMenuList } = s_permissionStore()
      const meta = to.meta as ExtendedRouteMeta
 
      // 1. 处理未认证用户
      if (!token) {
        if (WHITE_LIST.includes(to.path)) {
          return true
        }
        return LOGIN_PATH
      }
 
      // 2. 重定向已认证用户从登录页面
      if (to.path === LOGIN_PATH) {
        return '/'
      }
 
      // 3. 如果需要,初始化动态路由
      if (!authMenuList.length) {
        return await handleDynamicRouterInit(to.fullPath)
      }
 
      // 4. 设置页面标题并继续
      setPageTitle(meta.title)
      return true
    } catch (error) {
      return handleRouteError(error)
    }
  }
)

路由加载进度

系统使用NProgress在路由导航期间显示加载指示器:

scss 复制代码
const nprogress = setupNProgress()
 
// 导航前开始进度指示器
router.beforeEach(() => {
  nprogress.start()
})
 
// 导航后完成进度指示器
router.beforeEach(() => {
  // ...其他逻辑
  nprogress.done()
})

添加自定义路由

创建静态公共路由

要添加无需认证的新公共路由:

将您的路由添加到publicRouter.ts中的publicRoutes数组:

javascript 复制代码
export const publicRoutes: RouteRecordRaw[] = [
  // 现有路由...
  {
    path: '/public-dashboard',
    name: 'publicDashboard',
    component: () => import('@/views/public/Dashboard.vue'),
    meta: {
      title: 'Public Dashboard',
      icon: 'dashboard',
      hidden: false,
      keepAlive: true,
    },
  },
]

为后端集成创建动态路由

对于应包含在动态路由系统中的路由:

确保您的后端API以正确的格式返回路由定义:

css 复制代码
// 后端响应示例格式
{
  code: '0',
  data: [
    {
      path: '/dashboard',
      name: 'Dashboard',
      component: 'layout',
      redirect: '/dashboard/analysis',
      meta: { title: 'Dashboard', icon: 'dashboard' },
      children: [
        {
          path: 'analysis',
          name: 'Analysis',
          component: 'dashboard/Analysis',
          meta: { title: 'Analysis', keepAlive: true }
        }
      ]
    }
  ],
  msg: 'success'
}

src/views目录中创建与路由定义中的组件字符串匹配的视图组件。

常见路由模式

嵌套路由

使用父布局组件创建嵌套路由:

css 复制代码
{
  path: '/parent',
  component: 'layout',
  redirect: '/parent/child',
  meta: { title: 'Parent Menu' },
  children: [
    {
      path: 'child',
      component: 'parent/Child',
      meta: { title: 'Child Page' }
    }
  ]
}

带参数的路由

创建带动态参数的路由:

css 复制代码
{
  path: '/user/:id',
  component: 'user/Detail',
  meta: { title: 'User Detail' }
}

外部链接

创建链接到外部站点的菜单项:

rust 复制代码
{
  path: 'https://github.com/ChenyCHENYU/Robot_Admin',
  meta: { 
    title: 'GitHub Repository',
    link: true  // 此标志表示外部链接
  }
}

调试路由

在开发模式下,系统提供路由导航的调试日志:

javascript 复制代码
// 开发中的调试日志
if (import.meta.env.DEV)
  router.afterEach(to => console.debug('[动态路由] 导航至:', to.path))

您也可以在浏览器控制台中检查当前路由:

arduino 复制代码
// 在浏览器控制台
console.log(router.getRoutes())

最佳实践

  1. 组件懒加载:始终使用动态导入路由组件,以启用代码拆分并提高性能。
  2. 路由元属性:一致使用元属性控制路由在导航菜单和布局中的行为。
  3. 错误处理:为路由解析和导航实现适当的错误处理,以提供更好的用户体验。
  4. 测试:彻底测试您的路由,尤其是在实现动态路由生成时,确保所有路径正确解析。
  5. 路由名称:使用一致且描述性的路由名称,以便于调试和程序化导航。

总结

通过遵循这些指南并理解Robot Admin中的路由架构,您可以有效地实现和自定义应用程序所需的路由。Robot Admin的路由系统提供了完整的权限控制、动态路由生成和灵活的导航管理,为构建企业级应用奠定了坚实的基础。


相关链接:

期待共建!

如果这套组件系统对你的开发工作有所启发或帮助,请不要吝啬你的 Star!每一个 ⭐ 都是对我最大的鼓励和支持。

👉 点击这里 Star 支持项目 (🧧行大运摸大票💰)

🔗 探索更多资源

📋 资源类型 🔗 链接 📝 说明
🎯 在线预览 robotadmin.cn 体验完整功能演示
📚 详细文档 tzagileteam.com 深入了解实现细节
💻 源码仓库 https:/github.com/ChenyCHENYU/Robot_Admin 获取完整源代码
相关推荐
上海大哥25 分钟前
Flutter 实现工程组件化(Windows电脑操作流程)
前端·flutter
刘语熙33 分钟前
vue3使用useVmode简化组件通信
前端·vue.js
XboxYan1 小时前
借助CSS实现一个花里胡哨的点赞粒子动效
前端·css
码侯烧酒1 小时前
前端视角下关于 WebSocket 的简单理解
前端·websocket·网络协议
OEC小胖胖2 小时前
第七章:数据持久化 —— `chrome.storage` 的记忆魔法
前端·chrome·浏览器·web·扩展
OEC小胖胖2 小时前
第六章:玩转浏览器 —— `chrome.tabs` API 精讲与实战
前端·chrome·浏览器·web·扩展
不老刘2 小时前
基于clodop和Chrome原生打印的标签实现方法与性能对比
前端·chrome·claude·标签打印·clodop
ALLSectorSorft2 小时前
定制客车系统票务管理系统功能设计
linux·服务器·前端·数据库·apache
xiaopengbc2 小时前
B站,视频号怎么下载?,猫抓cat-catch离线版下载,Chrome扩展插件
前端·chrome
ZzMemory2 小时前
深入理解JS(九):IIFE,即执函数的锁域魔法
前端·javascript·面试