SiderMenu.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import React, { PureComponent, Suspense } from 'react';
  2. import { Layout } from 'antd';
  3. import classNames from 'classnames';
  4. import Link from 'umi/link';
  5. import styles from './index.less';
  6. import PageLoading from '../PageLoading';
  7. import { getDefaultCollapsedSubMenus } from './SiderMenuUtils';
  8. import { title } from '../../defaultSettings';
  9. const BaseMenu = React.lazy(() => import('./BaseMenu'));
  10. const { Sider } = Layout;
  11. let firstMount = true;
  12. export default class SiderMenu extends PureComponent {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. openKeys: getDefaultCollapsedSubMenus(props),
  17. };
  18. }
  19. componentDidMount() {
  20. firstMount = false;
  21. }
  22. static getDerivedStateFromProps(props, state) {
  23. const { pathname, flatMenuKeysLen } = state;
  24. if (props.location.pathname !== pathname || props.flatMenuKeys.length !== flatMenuKeysLen) {
  25. return {
  26. pathname: props.location.pathname,
  27. flatMenuKeysLen: props.flatMenuKeys.length,
  28. openKeys: getDefaultCollapsedSubMenus(props),
  29. };
  30. }
  31. return null;
  32. }
  33. isMainMenu = key => {
  34. const { menuData } = this.props;
  35. return menuData.some(item => {
  36. if (key) {
  37. return item.key === key || item.path === key;
  38. }
  39. return false;
  40. });
  41. };
  42. handleOpenChange = openKeys => {
  43. const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;
  44. this.setState({
  45. openKeys: moreThanOne ? [openKeys.pop()] : [...openKeys],
  46. });
  47. };
  48. render() {
  49. const { logo, collapsed, onCollapse, fixSiderbar, theme, isMobile } = this.props;
  50. const { openKeys } = this.state;
  51. const defaultProps = collapsed ? {} : { openKeys };
  52. const siderClassName = classNames(styles.sider, {
  53. [styles.fixSiderBar]: fixSiderbar,
  54. [styles.light]: theme === 'light',
  55. });
  56. return (
  57. <Sider
  58. trigger={null}
  59. collapsible
  60. collapsed={collapsed}
  61. breakpoint="lg"
  62. onCollapse={collapse => {
  63. if (firstMount || !isMobile) {
  64. onCollapse(collapse);
  65. }
  66. }}
  67. width={256}
  68. theme={theme}
  69. className={siderClassName}
  70. >
  71. <div className={styles.logo} id="logo">
  72. <Link to="/">
  73. <img src={logo} alt="logo" />
  74. <h1>{title}</h1>
  75. </Link>
  76. </div>
  77. <Suspense fallback={<PageLoading />}>
  78. <BaseMenu
  79. {...this.props}
  80. mode="inline"
  81. handleOpenChange={this.handleOpenChange}
  82. onOpenChange={this.handleOpenChange}
  83. style={{ padding: '16px 0', width: '100%' }}
  84. {...defaultProps}
  85. />
  86. </Suspense>
  87. </Sider>
  88. );
  89. }
  90. }