vue3+vue-router+vite 实现动态路由

[复制链接]
发表于 2026-1-31 13:05:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
文章中出现的代码是演示版本,仅供参考,实际的业务需求会更加复杂

什么是动态路由


什么场景会用到动态路由

举一个最常见的例子,比如说我们要开发一个背景管理体系,一样平常来说背景管理体系都会分脚色登录,这个时间也就涉及到了权限,比如说这个背景管理体系如今有超等管理员,管理员,运维,财政等这几个脚色,每个脚色登录体系之后都会有差别的权限,超等管理员必要全部的权限,财政大概只必要财政干系的模块(菜单)以及按钮等,通常实现这种需求会有以下常见方案
路由表由前端去维护

也就是说我们已知这几个脚色分别对应哪些权限,前端写好路由设置表,,后端只必要告诉你当前登录人是属于哪个脚色,前端根据脚色范例去写一个过滤函数,获取该脚色所拥有的菜单以及按钮,然后动态的去添加路由,如许做有一个缺点就是,如果又增长了一个新的脚色怎么办?某个脚色想增长一些权限怎么办?这个时间前端就必要去新增大概修改代码,一点也不友爱
路由表的数据由后端返回

这种也是常用的一种方式,大概我们的体系内里必要开发一些功能,如菜单管理,脚色管理,用户管理等,也就是常说的权限中央,前端开发完的页面所对应的路由信息有后端去维护,这个时间我们在开发的时间必要束缚某一种规则,比如全部页面都放到/src/views目的下面,然后通过菜单管理去维护数据,维护完的数据可以到脚色管理内里去设置脚色菜单,设置完脚色,可以到用户管理内里给某个用户设置脚色等一些列流程,如许的话纵然新增一个脚色,大概修改一个脚色的脚色菜单,前端都不必要去修改代码,只要在菜单管理内里维护好了数据,想怎么改怎么改,后端返回的数据格式大概如下:
  1. [
  2.   {
  3.     path: "/application",
  4.     name: "application",
  5.     component: "Layout",
  6.     title: "应用管理",
  7.     show: true,
  8.     icon: "",
  9.     children: [
  10.       {
  11.         path: "",
  12.         name: "application-index",
  13.         component: "/application/index.vue",
  14.       },
  15.     ],
  16.   },
  17.   {
  18.     path: "/permission",
  19.     name: "permission",
  20.     component: "Layout",
  21.     title: "权限管理",
  22.     show: true,
  23.     icon: "",
  24.     children: [
  25.       {
  26.         path: "menu",
  27.         name: "permission-menu",
  28.         component: "/permission/menu/index.vue",
  29.         title: "菜单管理",
  30.         show: true,
  31.         icon: "",
  32.       },
  33.       {
  34.         path: "user",
  35.         name: "permission-user",
  36.         component: "/permission/user/index.vue",
  37.         title: "用户管理",
  38.         show: true,
  39.         icon: "",
  40.       },
  41.       {
  42.         path: "role",
  43.         name: "permission-role",
  44.         component: "/permission/role/index.vue",
  45.         title: "角色管理",
  46.         show: true,
  47.         icon: "",
  48.       },
  49.     ],
  50.   },
  51. ]
复制代码
着实细致观察这个数据结构,是不是有点熟悉,path,name,component,children,我们似乎手动维护路由表的时间也会用到这些属性
怎样实现动态路由

实现动态路由着实就要用到vue-router提供的一个方法,叫addRoute在之前版本的时间是addRoutes,如今非版本的vue-router给废除了
addRoute()怎样利用呢?可以看一下官方文档
当我们添加一个主路由的时间
  1. router.addRoute({ path: '/permission', name: 'permission', component: () => import('xxxxx')})
复制代码
添加子路由也就是嵌套路由
  1. router.addRoute('主路由的name', { path: 'settings', component: AdminSettings })
复制代码

既然我们已经知道了addRoute()方法怎样利用,下面我们就可以去实现这部门逻辑
我们看一下官方文档的导航保卫内里的内容


在之前我们利用导航保卫的时间必要一个参数next()去控制是否放行以及去哪个页面,但是在新版本的vue-router内里可以不是用next(),固然你是用也行~
我们可以新建一个permission.ts文件
  1. import router from "./index";
  2. import { useSessionStorage } from "@vueuse/core";
  3. import { StorageEnum } from "@/enum";
  4. import { useUserStore } from "@/store";
  5. const whiteList = ["/login", "/404"];
  6. router.beforeEach(async (to) => {
  7.   const token = useSessionStorage(StorageEnum.TOKEN, "").value;
  8.   // 如果在白名单里面 并且 token 不存在
  9.   if (whiteList.includes(to.path) && !token) {
  10.     return true;
  11.   } else {
  12.     const { menuList, getMenuList } = useUserStore();
  13.     // 如果为空数组,name就请求接口重新获取后端维护的路由数据
  14.     if (!menuList.length) {
  15.       await getMenuList();
  16.       console.log("获取全部路由 =>", router.getRoutes());
  17.       // 触发重定向 不这样写会导致刷新找不到路由 两种写法都行
  18.       // return { path: to.fullPath };
  19.       return to.fullPath;
  20.     }
  21.   }
  22. });
复制代码
这里我们可以看到一会return true一会return to.fullpath是为什么,通过官方导航保卫内里的先容,我们可以知道的是

通过官方文档动态路由,我们可以直到

以是说return to.fullpath是官方告诉我们要这么利用,也是为相识决动态路由页面革新的时间会出现页面空缺大概404的标题
出现404的话比如说你在路由表中维护了下面路由映射
  1. {
  2. path: "/:pathMatch(.*)",
  3.   name: "page404",
  4.   component: () => import("@/views/system/404.vue"),
  5. }
复制代码
上面说的紧张是在全局导航保卫内里的一些利用及留意事项,我们可以看到并没有用到addRoute()这个方法,也没有出现拿到后端数据前端转换成路由表的干系代码,但是我们可以看到有一个getMenuList()函数,我们在开发的时间,肯定是要思量到复用以及复杂逻辑抽取的标题,一个动态路由的实现会扳连到很多知识点接口哀求,vuex大概pinia状态维护,vue-router,vite内里怎么获取文件等
下面看一下怎样获取到接口给的数据,转换成vue-router可以大概辨认的数据
起首我们要看一个vite官方给提供的功能,我们拿到后端给的文件路径如上面代码出现的component字段,如/application/index.vue,这个文件大概在我们当地项目中的src/views/application/index.vue这个路径下

我们必要把它转换成一个下面的格式() => import('xxxx'),我们必要动态的去拼接获取文件,该怎么实现呢?
vite官方文档中有分析

必要利用import.meta.glob,这个时间我们可以打印一下import.meta.glob("../views/**"),看一下返回的到底是什么

返回的是一个对象,而对象的key我们可以拼接获取到,而value正是我们想要的动态获取的文件路径
以下代码仅供参考,有很多必要美满的地方,只为演示利用
  1. import type { RouterType } from "@/router/type";
  2. import router from "@/router";
  3. import type { RouteRecordRaw } from "vue-router";
  4. export const useRouterConfig = () => {
  5.         // 获取views目录下的所有的文件 不要使用@别名
  6.   const modules = import.meta.glob("../views/**");
  7.   const asyncRoutes = ref<RouterType[]>([]);
  8.   const addRoutes = (menus: RouterType[]) => {
  9.     asyncRoutes.value = menus;
  10.     filterAsyncRouter();
  11.     // 动态添加 / 路由
  12.     router.addRoute({
  13.       path: "/",
  14.       redirect: asyncRoutes.value[0].path,
  15.     });
  16.   };
  17.   const filterAsyncRouter = () => {
  18.     const routerLoop = (routes: RouterType[], ParentName?: string) => {
  19.       routes.forEach((item) => {
  20.         if (item.component === "Layout") {
  21.           item.component = () => import("@/layout/index.vue");
  22.         } else {
  23.           item.component = resolveComponent(item.component);
  24.         }
  25.         const { title, show, icon, name, path, component, children } = item;
  26.         const route: RouteRecordRaw = {
  27.           component,
  28.           path,
  29.           name,
  30.           meta: {
  31.             title,
  32.             show,
  33.             icon,
  34.           },
  35.           children: children as any,
  36.         };
  37.                
  38.                 // 动态添加路由
  39.         if (ParentName) {
  40.           router.addRoute(ParentName, route);
  41.         } else {
  42.           router.addRoute(route);
  43.         }
  44.         if (item.children && item.children.length > 0) {
  45.           routerLoop(item.children, item.name);
  46.         }
  47.       });
  48.     };
  49.     routerLoop(asyncRoutes.value);
  50.   };
  51.   const resolveComponent = (path: string) => {
  52.     console.log(modules);
  53.     // 拿到views下面的所有文件之后,动态拼接`key`去获取value
  54.     const importPage = modules[`../views${path}`];
  55.     if (!importPage) {
  56.       throw new Error(
  57.         `Unknown page ${path}. Is it located under Pages with a .vue extension?`
  58.       );
  59.     }
  60.     return importPage;
  61.   };
  62.   return { addRoutes };
  63. };
复制代码
综上所述:
要想实现vite+vue-router实现动态路由我们必要用到


  • addRoute()
  • import.meta.glob()
  • 获取后端tree数据,递归循环,大概业务会有type范例,比如分为模块,菜单,页面,按钮等,到时间团结业务去实现逻辑
  • 导航保卫利用时的留意事项,否则会出现革新白屏,大概路由访问死循环等
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表