Vue中自动生成路由配置文件覆盖路由配置
设计思路
- 读取
@/views
下所有index.vue
如果当前文件下有包含相同路径则认为是它的子路由。 - 但也不能就这样写死,要创建
page.(ts|js)
配置文件也可以更改当前的配置,Page.(ts|js)
比重大于自动生成的路由配置。
踩坑点
坑点1
这里的'@/views'
不能使用变量传入。
ts
(require as any).context('@/views', true, /index\.vue$/)
坑点2
这里如果想对文件进行深度拷贝,直接使用三点(...)是不行的,这里借助了loadsh
中的merge
完成深度拷贝。
ts
// 导出当前存在的路由并重新赋值
const existingRoute = routeMap[route.path];
// 当前路由存在
if (existingRoute) {
const exportRouteConfig = context(fileInfo?.filePath).default;
// 使用loadsh合并对象
routeMap[route.path] = _.merge(existingRoute, exportRouteConfig);
}
代码编写
在vue中自动生成路由,并将目录下配置文件覆盖到原先路由配置。
ts
import { routeFilenameHelper } from '@/utils/file/routeFileUtil';
import _ from 'lodash';
import { RouteRecordRaw } from 'vue-router';
// * 最终路由
const routeMap: Record<string, RouteRecordRaw> = {};
// * 所有处理的路由
const contexts = [
{ context: (require as any).context('@/views', true, /index\.vue$/), isIndex: true },
{ context: (require as any).context('@/views', true, /page\.(ts|js)$/), isIndex: false },
];
/**
* 构建路由信息
* @param context 上下文信息
* @param isIndex 是否第一次遍历
* @param route 路由内容
*/
function buildRouteTree(context: any, isIndex: boolean, route: any) {
// 遍历当前子路由
context.keys().forEach((item: string) => {
// 获取子路由下所有文件对象格式
const childrenFileInfo = routeFilenameHelper(item, '/');
// 组装子路由对象
const childrenRoute: any = {
name: childrenFileInfo?.name,
path: childrenFileInfo!.path,
component: isIndex ? () => import(`@/views${childrenFileInfo?.replaceName}`) : undefined,
children: [],
meta: { isFullScreen: false },
};
// 如果当前路由对象等于当前遍历的路由子对象,将子路由推到父级路由中
if (childrenFileInfo?.path.includes(route.path) && childrenFileInfo?.path !== route.path) {
route.children.push(childrenRoute);
}
});
}
/**
* 遍历路由信息
* @param context 路由上下文
* @param isIndex 是否为索引遍历
*/
const createRouteList = (context: any, isIndex: boolean) => {
// 遍历文件下所有路径
context.keys().forEach((filePath: string) => {
const fileInfo = routeFilenameHelper(filePath, '/');
// 组装路由对象
const route: RouteRecordRaw = {
name: fileInfo?.name,
path: fileInfo!.path,
component: isIndex ? () => import(`@/views${fileInfo?.replaceName}`) : undefined,
children: [],
meta: { isFullScreen: false },
};
// * 如果是第一次遍历 初始化赋值
if (isIndex) {
routeMap[route.path] = route;
buildRouteTree(context, isIndex, route);
}
// * 读取配置文件中内容
else {
// 导出当前存在的路由并重新赋值
const existingRoute = routeMap[route.path];
// 当前路由存在
if (existingRoute) {
const exportRouteConfig = context(fileInfo?.filePath).default;
// 使用loadsh合并对象
routeMap[route.path] = _.merge(existingRoute, exportRouteConfig);
}
}
});
};
// * 生成路由信息
contexts.forEach(({ context, isIndex }) => createRouteList(context, isIndex));
// * 返回生成好的路由
export const pageRoutes: Array<RouteRecordRaw> = Object.values(routeMap);