vue3动态路由
要想实现vite+vue-router实现动态路由我们需要用到
1. addRoute()
官方文档中addRoute的使用
当我们添加一个主路由的时候
router.addRoute({ path: '/permission', name: 'permission', component: () => import('xxxxx')})
添加子路由也就是嵌套路由
router.addRoute('主路由的name', { path: 'settings', component: AdminSettings })
2. 导航守卫使用时的注意事项,否则会出现刷新白屏,或者路由访问死循环等
之前我们使用导航守卫的时候需要一个参数next()
去控制是否放行以及去哪个页面,但是在新版本的vue-router
里面可以不是用next()
我们可以新建一个permission.ts文件
import router from "./index";
import { useSessionStorage } from "@vueuse/core";
import { StorageEnum } from "@/enum";
import { useUserStore } from "@/store";
const whiteList = ["/login", "/404"];
router.beforeEach(async (to) => {
const token = useSessionStorage(StorageEnum.TOKEN, "").value;
// 如果在白名单里面 并且 token 不存在
if (whiteList.includes(to.path) && !token) {
return true;
} else {
const { menuList, getMenuList } = useUserStore();
// 如果为空数组,name就请求接口重新获取后端维护的路由数据
if (!menuList.length) {
await getMenuList();
console.log("获取全部路由 =>", router.getRoutes());
// 触发重定向 不这样写会导致刷新找不到路由 两种写法都行
// return { path: to.fullPath };
return to.fullPath;
}
}
});
出现404的话比如说你在路由表中维护了下面路由映射
{
path: "/:pathMatch(.*)",
name: "page404",
component: () => import("@/views/system/404.vue"),
}
3. 获取后端tree数据,递归循环,可能业务会有type类型,比如分为模块,菜单,页面,按钮等,到时候结合业务去实现逻辑
4.import.meta.glob()
import.meta.glob动态的去拼接获取文件,把后台返回内容转换成() => import('xxxx')格式
以下代码仅供参考,有很多需要完善的地方
import type { RouterType } from "@/router/type";
import router from "@/router";
import type { RouteRecordRaw } from "vue-router";
export const useRouterConfig = () => {
// 获取views目录下的所有的文件 不要使用@别名
const modules = import.meta.glob("../views/**");
const asyncRoutes = ref<RouterType[]>([]);
const addRoutes = (menus: RouterType[]) => {
asyncRoutes.value = menus;
filterAsyncRouter();
// 动态添加 / 路由
router.addRoute({
path: "/",
redirect: asyncRoutes.value[0].path,
});
};
const filterAsyncRouter = () => {
const routerLoop = (routes: RouterType[], ParentName?: string) => {
routes.forEach((item) => {
if (item.component === "Layout") {
item.component = () => import("@/layout/index.vue");
} else {
item.component = resolveComponent(item.component);
}
const { title, show, icon, name, path, component, children } = item;
const route: RouteRecordRaw = {
component,
path,
name,
meta: {
title,
show,
icon,
},
children: children as any,
};
// 动态添加路由
if (ParentName) {
router.addRoute(ParentName, route);
} else {
router.addRoute(route);
}
if (item.children && item.children.length > 0) {
routerLoop(item.children, item.name);
}
});
};
routerLoop(asyncRoutes.value);
};
const resolveComponent = (path: string) => {
console.log(modules);
// 拿到views下面的所有文件之后,动态拼接`key`去获取value
const importPage = modules[`../views${path}`];
if (!importPage) {
throw new Error(
`Unknown page ${path}. Is it located under Pages with a .vue extension?`
);
}
return importPage;
};
return { addRoutes };
};