1.理解路由表
在Vue Router中,使用router.addRoute可以动态添加路由。关于路由的组织方式,有两种常见的模式:嵌套路由和扁平化路由。
-
嵌套路由:
-
优势: 嵌套路由更贴近实际页面结构,可以更好地反映应用的层级关系。适用于有层级结构的页面,比如页面内有多个组件组成,或者需要进行布局嵌套的情况。
-
示例:
const routes = [ { path: '/dashboard', component: Dashboard, children: [ { path: 'profile', component: Profile }, { path: 'settings', component: Settings } ] } ];
-
-
扁平化路由:
-
优势: 扁平化路由则更适用于简单的页面结构,每个路由平等地存在于路由层级中,不再嵌套。适用于页面较简单,层级关系不明显的情况。
-
示例:
const routes = [ { path: '/dashboard', component: Dashboard }, { path: '/profile', component: Profile }, { path: '/settings', component: Settings } ];
-
为什么有些人更喜欢进行路由扁平化,取决于项目的实际需求和团队的开发习惯。在某些情况下,扁平化路由可能更容易维护,特别是在应用比较简单,不需要多层嵌套的情况下。另一方面,如果应用有复杂的层级结构,嵌套路由可以更好地组织和管理代码。因此,选择哪种方式取决于具体的项目需求和开发团队的偏好。
那扁平化的路由,是怎么被识别为一级路由 二级路由呢?
在扁平化的路由中,一级路由和二级路由之间的关系通常是通过path属性来识别的。一级路由的path是根据项目的根路径定义的,而二级路由的path则是在一级路由的基础上追加的。
例如,考虑以下扁平化路由的例子:
const routes = [
{
path: '/dashboard',
component: Dashboard
},
{
path: '/profile',
component: Profile
},
{
path: '/settings',
component: Settings
}
];
在这里,'/dashboard'、'/profile'和'/settings'分别可以被认为是一级路由。如果你想要将它们视为二级路由,可以调整path的定义。例如,将'/dashboard'改为'/dashboard/home','/profile'改为'/profile/info','/settings'改为'/settings/preferences'等。这样就可以在/dashboard、/profile和/settings下分别添加更多的二级路由。
总的来说,路由的层级关系在于path的定义。通过定义不同层级的path,你可以在Vue Router中实现一级路由和二级路由的结构。
2.动态添加路由
router.addRoute('name', {
path:'/',
component:()=>import('')
})
可以理解为将路由表中的路由删除掉,通过router.addRoute 去动态添加这部分被注释的路由信息
然后将这部分路由信息放到后端,
通过在views下创建对应后端返回中path字段的文件夹和文件,然后通过import.meta.glob('@renderer/views/**/*.vue');去检索到对应的.vue文件,将后端中component字段从字符串换成()=>import('')格式
需要把后端给前端返回的路由数据的component对应的value字符串修改成:component:()=>import('')
export const beforeEach = ( to )=>{
initRouter()
//当前路由没有匹配到任何路由记录
if(to.matched.length == 0){
router.push(to.fullPath)
}
}
import { useMenuStore } from '@store/useMenuStore'
import router from '@router'
import { Parent } from '@interface/user'
export const beforeEach = ( to:any )=>{
if( to.path == '/login' ){
return ;
}
if( !localStorage.getItem('TOKEN') ){
return '/login'
}
//动态添加路由
initRouter();
//当前路由没有匹配到任何路由记录
if( to.matched.length == 0){
router.push( to.fullPath );
}
return true;
}
interface Child{
parentView: string;
path: string;
name: string;
meta: any;
redirect: string;
children?: Child[] | null;
component: any;
id?: string | undefined;
hidden?: boolean | undefined;
alwaysShow?: boolean | undefined;
query?: string | undefined;
}
interface Child extends Omit<Parent, 'children'> {
children?: Child[] | null;
}
//1. 动态添加路由 => 整个过程
const initRouter = ()=>{
let menu:Parent[] = useMenuStore().menu;
let menuRouter: Child[] = filterRouter(menu);
menuRouter = flatRoutes(menuRouter);
menuRouter.forEach((item:any) => {
router.addRoute(item.parentView == 'layout' ? 'layout' : '', item);
});
}
//2. 把component 重构成 箭头函数的形式
const filterRouter = (menu: Parent[]): Child[] => {
let arrRouter: Child[] = [];
menu.forEach((item: any) => {
var route: Child = {
parentView: item.parentView,
path: item.path,
name: item.name,
meta: item.meta,
redirect: item.redirect,
children: item.children ? filterRouter(item.children) : null,
component: loadComponent(item.component)
};
arrRouter.push(route);
});
return arrRouter;
};
//3. 对于component的调整
const modules: Record<string, () => Promise<any>> = import.meta.glob('@renderer/views/**/*.vue');
const modulesMap: Record<string, () => Promise<any>> = {};
Object.keys(modules).forEach((key) => {
const componentName = key.replace('/src/views', '').replace('.vue', '').replace('/index', '').replace('/', '');
if (key.includes('index')) {
modulesMap[`${componentName}/index`] = modules[key];
}
modulesMap[componentName] = modules[key];
});
//4. 根据modulesMap[key]返回对应的value值
const loadComponent = (component: string | null): (() => Promise<any>) | undefined => {
if (component) {
return modulesMap[component];
}
return;
};
//5. 路由扁平化
const flatRoutes = (routes: Child[], breadcrumb: Child[] = []): Child[] => {
let res: Child[] = [];
routes.forEach((route: Child) => {
const tmp = { ...route };
if (tmp.children) {
let childrenBreadcrumb: Child[] = [...breadcrumb];
childrenBreadcrumb.push(route);
let tmpRoute = { ...route };
delete tmpRoute.children;
res.push(tmpRoute);
let childrenRoutes = flatRoutes(tmp.children, childrenBreadcrumb);
childrenRoutes.map((item) => {
res.push(item);
});
} else {
let tmpBreadcrumb = [...breadcrumb];
tmpBreadcrumb.push(tmp);
res.push(tmp);
}
});
return res;
};
//后置
export const afterEach = ()=>{
console.log('后置');
}