react 封装antd menu组件,路由懒加载,可折叠,可配置显示和隐藏,刷新后选择正确的菜单,打开正确的submenu
import React, { useEffect, useState, useMemo } from 'react'
import { Menu } from 'antd'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import Icon from '../../../components/light/Icon'
import Logo from './Logo'
const { SubMenu } = Menu
function Sidebar(props) {
const {
router,
location: { pathname },
theme,
selectedKeys,
collapsed,
} = props
const [openKeys, setOpenKeys] = useState([])
const defaultOpenKeysFn = () => {
const arr = []
let myPathname = pathname.replace(/(\/+$)/g, '')
let arrTemp = myPathname.split('/')
if (arrTemp.length > 4) {
for (let i = 4; i < arrTemp.length; i++) {
arr.push(arrTemp.slice(0, i).join('/'))
}
}
return arr
}
const handleNav = (path) => {
//props.onSetState(['selectedKeys'], path)
props.history.push(path)
}
const isFirstLevel = (item) => {
const pathLength = item.key.split('/').length
return pathLength === 4
}
// 只有router、collapsed变化时才会重新渲染sidebarDom,useMemo函数可以起到性能优化的作用
const sidebarDom = useMemo(() => {
const sidebarRender = (arr) => {
return arr.map((item) => {
if (item.children) {
if (item.isVisible) {
// 一级子菜单折叠时使用大图标
return (
<SubMenu
key={item.key}
title={item.title}
className={item.className ? item.className : ''}
icon={
item.icon ? (
<span className="anticon anticon-appstore m-sidebar-icon-wrap">
<Icon
name={item.icon}
className={`m-sidebar-icon ${
collapsed && isFirstLevel(item)
? 'big'
: ''
}`}
></Icon>
</span>
) : null
}
>
{sidebarRender(item.children)}
</SubMenu>
)
} else {
return null
}
} else {
// 使用span包裹Icon组件,并添加antd的className才能正确使用Menu的icon属性
// 折叠时使用大图标
if (item.isVisible) {
// 有些菜单只在开发环境展示
if (!item.isDevMenu || process.env.REACT_APP_MODE === 'dev'){
if(item.hiddenMenu!==false){
return (
<Menu.Item
key={item.path}
className={item.className ? item.className : ''}
onClick={() => handleNav(item.path)}
icon={
item.icon ? (
<span className="anticon anticon-appstore m-sidebar-icon-wrap">
<Icon
name={item.icon}
className={`m-sidebar-icon ${collapsed ? 'big' : ''}`}
></Icon>
</span>
) : null
}
>
<span>{item.title}</span>
</Menu.Item>
)
}else{
return null;
}
} else {
return null
}
} else {
return null
}
}
})
}
return sidebarRender(router.toJS())
// eslint-disable-next-line
}, [router, collapsed])
const handleOpenChange = (openKeys) => {
setOpenKeys(openKeys)
}
useEffect(() => {
props.onSetState(['selectedKeys'], pathname)
// eslint-disable-next-line
}, [pathname])
useEffect(() => {
if (!collapsed) {
setOpenKeys(defaultOpenKeysFn())
}
// eslint-disable-next-line
}, [collapsed])
return (
<Menu
selectedKeys={[selectedKeys]}
openKeys={openKeys}
style={{ width: collapsed ? 80 : 256, height: '100%', overflowY: 'auto' }}
mode="inline"
theme={theme}
inlineCollapsed={collapsed}
onOpenChange={handleOpenChange}
>
<Logo collapsed={collapsed}></Logo>
{sidebarDom}
</Menu>
)
}
const mapStateToProps = (state) => {
return {
router: state.getIn(['light', 'router']),
theme: state.getIn(['light', 'theme']),
selectedKeys: state.getIn(['light', 'selectedKeys']),
collapsed: state.getIn(['light', 'collapsed']),
userInfo: state.getIn(['light', 'userInfo']).toJS(),
}
}
const mapDispatchToProps = (dispatch) => {
return {
onSetState(key, value) {
dispatch({ type: 'SET_LIGHT_STATE', key, value })
},
onDispatch(action) {
dispatch(action)
},
}
}
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Sidebar))
router.js:
import { lazy } from 'react'
// isDevMenu=true只在开发环境显示
const router = [
{
title: '首页',
icon: 'home',
className: 'm-sidebar-home',
isVisible: true,
path: '/sale/index/home',
component: lazy(() => import('../../views/light/index/home/Home'))
},
{
title: 'xx管理',
icon: 'base',
isVisible: true,
key: '/sale/index/offline',
children: [
{
title: 'xx管理',
icon: '',
isVisible: true,
path: '/sale/index/offline/companyList',
component: lazy(() => import('../../views/sale/index/offline/companyList/Index'))
},
{
title: 'xx管理',
icon: '',
isVisible: true,
path: '/sale/index/offline/shopList',
component: lazy(() => import('../../views/sale/index/offline/shopList/Index'))
},
]
},
]
export default router