src/moaels/menu.js
import { getMenuData } from '@/services/menu'
import { loginOut } from '@/services/api'
const MenuModel= {
namespace: 'menu',
state: {
menuData: [],
loading: true,
},
effects: {
*fetchMenu(_, { call, put }) {
const response = yield call(getMenuData)
yield put({
type: 'saveMenuData',
payload: response.data,
})
},
//清除保存的服务器菜单数据
*clearMenu(_, { call, put }) {
const response = yield call(loginOut)
yield put({
type: 'clearMenuData',
payload: [],
})
}
},
reducers: {
saveMenuData(state, action) {
return {
...state,
menuData: action.payload || [],
loading: false,
}
},
clearMenuData(state,action){
return {
...state,
menuData: [],
loading: true,
}
}
}
}
export default MenuModel
退出登录时需要清除保存的服务器菜单数据,不然登录其他账号会加载上个账号的菜单
const { dispatch} =this.props
dispatch({
type: 'menu/clearMenu',
});
api接口
src/services/menu.js
import request from '@/utils/request'
export async function getMenuData() {
return request('/api/menu')
}
侧边渲染
src/layouts/basiclayout.jsx
/**
* Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout.
* You can view component api by:
* https://github.com/ant-design/ant-design-pro-layout
*/
import ProLayout, { DefaultFooter, SettingDrawer } from '@ant-design/pro-layout';
import React, { useEffect, useMemo, useRef } from 'react';
import { Link, useIntl, connect, history } from 'umi';
import { Result, Button } from 'antd';
import Authorized from '@/utils/Authorized';
import RightContent from '@/components/GlobalHeader/RightContent';
import { getMatchMenu } from '@umijs/route-utils';
import logo from '../assets/logo.svg';
const noMatch = (
<Result
status={403}
title="403"
subTitle="您暂时没有权限查看此页面。"
extra={
<Button type="primary">
<Link to="/user/login">去登录</Link>
</Button>
}
/>
);
/**
* use Authorized check all menu item
*/
// const menuDataRender = (menuList) =>
// menuList.map((item) => {
// item.name = item.code
// const result = {
// ...item,
// };
// if(item.routes){
// const children = menuDataRender(item.children)
// result.children = children
// }
// delete result.routes
// return Authorized.check(item.authority, result);
// });
const formatter = (data, parentAuthority, parentName) => {
if (!data) {
return undefined
}
return data
.map(item => {
if (!item.path) {
return null
}
const name = item.code
const result = {
...item,
name,
authority: item.authority || parentAuthority
}
if (item.routes) {
const children = formatter(item.routes, item.authority)
result.children = children
}
delete result.routes
return result
})
.filter(item => item)
}
const defaultFooterDom = (
<DefaultFooter copyright={`${new Date().getFullYear()} 广东高乐教育科技有限公司`} links={false} />
);
const BasicLayout = (props) => {
const {
dispatch,
children,
location = {
pathname: '/',
},
menuData,
loading,
settings,
} = props;
const menuDataRef = useRef([]);
useEffect(() => {
if (dispatch) {
dispatch({
type: 'menu/fetchMenu',
});
}
}, []);
/**
* init variables
*/
const handleMenuCollapse = (payload) => {
if (dispatch) {
dispatch({
type: 'global/changeLayoutCollapsed',
payload,
});
}
}; // get children authority
const authorized = useMemo(
() =>
getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
authority: undefined,
},
[location.pathname],
);
const { formatMessage } = useIntl();
return (
<>
<ProLayout
logo={logo}
formatMessage={formatMessage}
{...props}
{...settings}
onCollapse={handleMenuCollapse}
onMenuHeaderClick={() => history.push('/')}
menuItemRender={(menuItemProps, defaultDom) => {
if (menuItemProps.isUrl || !menuItemProps.path) {
return defaultDom;
}
return <Link to={menuItemProps.path}>{defaultDom}</Link>;
}}
breadcrumbRender={(routers = []) => [
{
path: '/',
breadcrumbName: formatMessage({
id: 'menu.home',
}),
},
...routers,
]}
itemRender={(route, params, routes, paths) => {
const first = routes.indexOf(route) === 0;
return first ? (
<Link to={paths.join('/')}>{route.breadcrumbName}</Link>
) : (
<span>{route.breadcrumbName}</span>
);
}}
footerRender={() => defaultFooterDom}
menuDataRender={() => formatter(menuData)}
menu={{
loading,
}}
rightContentRender={() => <RightContent />}
postMenuData={(menuData) => {
//这是权限判断,不去掉可能会页面403
// menuDataRef.current = menuData || [];
return menuData || [];
}}
>
<Authorized authority={authorized.authority} noMatch={noMatch}>
{children}
</Authorized>
</ProLayout>
</>
);
};
export default connect(({ global, settings, menu }) => ({
collapsed: global.collapsed,
menuData: menu.menuData,
loading: menu.loading,
settings
}))(BasicLayout);
本文介绍了如何在AntdPro4中结合JavaScript实现服务器动态获取并设置菜单的功能。在用户退出登录时,为了确保清空菜单数据,防止加载先前账号的菜单信息,文中提及了在`src/models/menu.js`中处理此逻辑,并详细讲解了如何调用`src/services/menu.js`中的API接口获取菜单,并在`src/layouts/basiclayout.jsx`中进行侧边栏的渲染。
1543

被折叠的 条评论
为什么被折叠?



