动态获取菜单
先看实现效果
官方提供的动态菜单实现方法:菜单的高级用法 - Ant Design Pro
前提说明:实现动态路由时,所有的路由都必须提前在 config/routes.ts
中注册好,如果动态返回了 routes.ts
中不存在的路由信息,页面将会无法访问,具体问题可参考(Issue #11137)。只能动态返回 routes.ts
内的数据
修改 app.tsx
的 layout 方法,在配置中添加 menu
属性即可实现动态菜单
// ProLayout 支持的api https://procomponents.ant.design/components/layout
export const layout: RunTimeLayoutConfig = ({ initialState, setInitialState }) => {
return {
// ... 省略其他代码
menu: {
// 每当 initialState?.currentUser?.userid 发生修改时重新执行 request
params: {
userId: initialState?.currentUser?.userId,
roleIds: initialState?.currentUser?.sysRoleList?.map((item) => item.roleId),
},
request: async (params, defaultMenuData) => {
// 调用接口获取菜单数据
let { data } = await getRoleMenuFun(params.roleIds);
if (data.length > 0) {
return data;
}
return defaultMenuData;
},
},
// 手动映射icon
menuDataRender: (menuData) => fixMenuItemIcon(menuData),
};
};
接口返回的data菜单格式和 config/routes.ts
中配置的保持一致,更多配置可以参考:Pro 的 Layout 组件 - Ant Design Pro
返回内容示例:
{
path: '/user/login',
layout: false, // 页面是否在layout布局样式下显示,设置成false会单独显示
hideInMenu: true, // 是否隐藏菜单,这里只是设置不在左侧菜单列表中显示,仍可以访问
name: '登录',
component: './Login',
},
{
path: '/welcome',
name: '欢迎',
icon: 'smile',
component: './Welcome',
},
{
path: 'test',
name: '一级菜单',
routes: [
{
path: 'test1',
name: '二级菜单1',
routes: [
{
path: 'test1-1',
name: '三级菜单1-1',
component: './Test',
},
{
path: 'test1-2',
name: '三级菜单1-2',
component: './Test',
},
],
},
{
path: 'test2',
name: '二级菜单2',
component: './Test',
},
],
},
当我们使用了动态返回的菜单时,图标就不出现了,这时需要手动映射icon图标,可参考这里
添加 src/utils/fixMenuItemIcon.ts
文件
import React from 'react';
import * as allIcons from '@ant-design/icons';
// FIX从接口获取菜单时icon为string类型
const fixMenuItemIcon = (menus, iconType = 'Outlined') => {
menus.forEach((item) => {
const { icon, children } = item;
if (typeof icon === 'string') {
let fixIconName = icon.slice(0, 1).toLocaleUpperCase() + icon.slice(1) + iconType;
console.log(fixIconName, 'fixIconName');
item.icon = React.createElement(allIcons[fixIconName] || allIcons[icon]);
}
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
children && children.length > 0 ? (item.children = fixMenuItemIcon(children)) : null;
});
return menus;
};
export default fixMenuItemIcon;
这里二级菜单的图标没有,官方是这样解释的
最终实现的效果,先给管理员和普通和用户分配不同的菜单
切换登录不同角色的用户,会显示不同的菜单
实现过程中遇到的问题以及解决方法
- 请问菜单从服务端获取,为什么还要在 routes 配置好全部,否则就不能正常解析 · Issue #11137 · ant-design/ant-design-pro (github.com)
- 动态菜单实现后,路由是全部的,可以通过url跳转到不显示的菜单项BUG] · Issue #10728 · ant-design/ant-design-pro (github.com)
实现源码
https://gitee.com/szxio/user-center