Sider菜单案例,把 md后缀修改为 zip,然后解压缩
Sider.md
使用 Sider
import Sider from '@layouts/Sider';
const data = [
{
name: '仪表盘',
icon: 'dashboard',
path: '/dashboard', // before is 'dashboard'
children: [
{
name: '分析页',
path: '/dashboard/analysis', // before is 'analysis'
children: [
{
name: '实时数据',
path: '/dashboard/analysis/realtime', // before is 'realtime'
},
{
name: '离线数据',
path: '/dashboard/analysis/offline', // before is 'offline'
},
],
},
],
},
{
name: '列表页',
icon: 'list',
path: '/list',
},
];
function App() {
const { pathname } = props.location;
return (
<Sider
pathname={pathname}
menuData={data}
/>
)
}
Sider.jsx
import React, { useState, useEffect } from 'react';
import { number, string, array, arrayOf, shape } from 'prop-types';
import { Link } from 'dva/router';
import { Menu } from 'antd';
import { getSelectedKeys } from './utils';
const { SubMenu, Item } = Menu;
// submenu keys of first level
const rootSubmenuKeys = ["/dashboard", "/list", "/"];
Sider.propTypes = {
width: number,
pathname: string,
menuData: arrayOf(shape({
name: string,
path: string,
icon: string,
children: array,
})),
};
Sider.defaultProps = {
menuData: [],
width: 200,
pathname: '/',
};
function Sider(props) {
const { menuData, pathname, width } = props;
// 初始值不能为空,否则切换路由,菜单会先收起,然后在展开;有闪烁问题
const [state, setState ] = useState(getSelectedKeys({menuData,pathname}));
useEffect(update, [pathname, menuData]);
function update() {
const newKeys = getSelectedKeys({menuData,pathname});
setState(newKeys)
}
function onOpenChange(keys) {
// setState(prevState => ({...prevState, openKeys}));
let openKeys = keys
// 如果没找到
const latestOpenKey = keys.find((key) => !state.openKeys.includes(key));
if (!rootSubmenuKeys.includes(latestOpenKey)) {
openKeys = keys;
} else {
openKeys = latestOpenKey ? [latestOpenKey] : []
}
setState(prevState => ({...prevState, openKeys}));
}
function renderMenu(data) {
return data.map((item) => {
const { children, path, name } = item;
if (children && children.length) {
return (
<SubMenu
key={path}
title={
<span>{name}</span>
}
>
{renderMenu(children)}
</SubMenu>
);
}
return (
<Item key={path}>
<Link to={path} href={path}>
<span>{name}</span>
</Link>
</Item>
);
})
}
const { openKeys, selectedKeys } = state;
const MenuProps = {
mode:'inline',
theme:'dark',
// inlineCollapsed: true, // 收起菜单
openKeys, // 当前展开的 SubMenu菜单项
selectedKeys, // 选中的菜单项 key 数组
onOpenChange,
}
console.log('state', state)
return (
<div style={{ width }}>
<Menu {...MenuProps}>
{renderMenu(menuData)}
</Menu>
</div>
);
}
export default Sider;
菜单闪烁问题
openKeys初始值不能为空数组
否则切换路由,菜单会先收起,然后在展开;有闪烁问题
const [state, setState] = useState({
openKeys: [],
selectedKeys: [],
});
useEffect(update, [pathname, menuData]);
function update() {
const pathArray = getFlatMenuKeys(menuData);
const selectedKeys = getMenuMatchKeys(pathArray, urlToList(pathname));
setState({
openKeys: selectedKeys,
selectedKeys,
});
}