比如说需要配置个大概下面效果的菜单。
新建相关页面模块
首先,需要在 src/pages 下新建所需页面的模块。
直接在 route.config.ts 中配置路由
由于使用的是 umi 内置的 layout,所以在 umi 中无需去关心左侧菜单栏的设计,直接配置好相对于的路由,它会自动帮你生成相对于的菜单。
下面直接贴上 routes 的配置数据,需注意其书写格式,否则可能会造成菜单栏无法展示出来的问题。
const route = [
{
name: '登录',
path: '/login',
component: '@/pages/Login',
hideInMenu: true,
layout: false,
},
{
path: '/404',
component: '@/pages/404Page',
},
{
path: '/',
redirect: '/postManager',
},
{
name: '帖子管理',
path: '/postManager',
component: '@/layouts',
icon: 'home',
hideChildrenInMenu: true,
routes: [
{
name: '帖子管理',
path: '/postManager',
component: '@/pages/PostManager/List',
},
{
name: '帖子详情',
path: '/postManager/detail',
component: '@/pages/PostManager/PostDetail',
},
{
redirect: '/404',
},
],
},
{
name: '委托管理',
icon: 'home',
path: '/entrustManager',
component: '@/layouts',
routes: [
{
name: '全部委托',
path: '/entrustManager/all',
component: '@/pages/EntrustManager/AllEntrust',
},
{
name: '全部委托详情',
path: '/entrustManager/all/detail',
component: '@/pages/EntrustManager/EntrustDetail',
hideInMenu: true,
},
{
name: '已同步委托',
path: '/entrustManager/synced',
component: '@/pages/EntrustManager/SyncedEntrust',
},
{
name: '已同步委托详情',
path: '/entrustManager/synced/detail',
component: '@/pages/EntrustManager/EntrustDetail',
hideInMenu: true,
},
{
redirect: '/404',
},
],
},
{
name: '用户管理',
path: '/userManager',
component: '@/layouts',
icon: 'home',
hideChildrenInMenu: true,
routes: [
{
name: '用户管理',
path: '/userManager',
component: '@/pages/UserManager/List',
},
{
name: '帖子详情',
path: '/userManager/detail',
component: '@/pages/UserManager/UserDetail',
},
{
redirect: '/404',
},
],
},
{
redirect: '/404',
},
];
export default route;
注意点:
- 有一级菜单但是不需要展示二级菜单,如上面的帖子管理。使用
hideChildrenInMenu: true进行隐藏, - 有一级菜单且也有二级菜单,但其下面的部分菜单不需要展示,使用
hideInMenu: true进行隐藏。如上面的那些委托详情。 - 不需要展示到菜单栏的路由,如登录页,使用
hideInMenu: true进行隐藏。(umi的layout默认是会把配置的全部路由都自动生成为左侧菜单,所以菜单的显隐需要自己去控制)。 - 上面登录页这个设置后,虽然左侧菜单栏没有登录的菜单了,但是如果我们访问登录页的话,会看到它展示在
layout的content中(简单说就是还是存在菜单栏),如何做到页面全屏展示?这个时候就还需要配置layout: false
路由优化
看上面路由的配置信息,没有几个页面,就已经快上百行了,如果一个项目的模块比较多的话,能达到成百上千不是问题,所以可以针对这个进行优化一下。
我的思路是:
将各模块的路由配置在各自的页面模块下,如上面的的用户管理的路由就配置在 src/pages/UserManager 目录下。
然后在 config/routes.config.ts 文件中统一导入合并,然后再统一导出赋值给 umi 的 route 配置
以上面例子三个模块为例,可分别在其对应的模块下新建三个路由配置文件。
注意导出的方式,是以 nodejs 的方式导出的。所有的路由配置文件都是 cmd 环境的,并不是 es6 环境的,因为下面需要使用 nodejs 的一些 API 来读取这些配置文件的配置内容进行整合处理。
在 config/routes.config.ts 文件下使用 nodejs 的方式进行统一导入。然后再在这个文件整合所有路由统一导出。
/*
* @Description: 路由配置文件
* @Author: kivet
* @Date: 2022-01-29 13:52:34
* @LastEditTime: 2022-01-29 17:56:43
*/
const path = require('path');
const fs = require('fs');
/**
* 读取 pages 目录下所有页面模块的路由配置,注:路由配置文件名,必须以 route[.***].(ts|js) 的格式命名
* @param dir 目录
* @param useSubDir 是否读取子目录
*/
const generateRoutes = (pagesDir: string, useSubDir: boolean) => {
const routeFileList: any = [];
const readRouteFileList = (_dir: string, _useSubDir: boolean) => {
const files = fs.readdirSync(_dir);
files.forEach((item: any) => {
// 生成
const filePath = path.join(_dir, item);
const stat = fs.statSync(filePath);
// 判断是否为目录
if (stat.isDirectory() && _useSubDir) {
readRouteFileList(path.join(_dir, item), _useSubDir);
} else {
const reg = RegExp(/route(.*).ts|js/);
if (reg.test(filePath)) {
routeFileList.push(filePath);
}
}
});
};
// 递归读取路由配置文件
readRouteFileList(pagesDir, useSubDir);
const routes = routeFileList.map((item: string) => require(item));
return routes;
};
/**
* 读取pages目录下路由文件,自动生成路由表
*/
const routes = generateRoutes(path.join(__dirname, '../src/pages'), true);
export default [
{
name: '登录',
path: '/login',
component: '@/pages/Login',
hideInMenu: true,
layout: false,
},
{
path: '/404',
component: '@/pages/404Page',
},
{
path: '/',
redirect: '/postManager',
},
...routes,
{
redirect: '/404',
},
];
核心代码即使上面的 generateRoutes() 函数,他是使用的 nodejs 的方式去读取 pages 目录下所有以 route[.***].(ts|js) 的格式命名的路由配置文件的数据。
这样写的好处就是,之后你新增其它模块的路由配置时,不需要每新增一个就得在这里导入整合一次,直接一步到位,之后就可以随便加新的模块了。