SiderMenu.tsx 3.3 KB
Newer Older
1
import { Layout } from 'antd';
afc163's avatar
afc163 committed
2
import classNames from 'classnames';
3 4
import * as H from 'history';
import React, { Component, Suspense } from 'react';
zinkey's avatar
zinkey committed
5
import Link from 'umi/link';
6
import defaultSettings from '../../../config/defaultSettings';
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
7
import PageLoading from '../PageLoading';
8
import styles from './index.less';
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
9
import { getDefaultCollapsedSubMenus } from './SiderMenuUtils';
jiang's avatar
jiang committed
10

ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
11
const BaseMenu = React.lazy(() => import('./BaseMenu'));
jim's avatar
jim committed
12
const { Sider } = Layout;
13 14
const { title } = defaultSettings;
let firstMount: boolean = true;
jiang's avatar
jiang committed
15

16 17
export declare type CollapseType = 'clickTrigger' | 'responsive';
export declare type SiderTheme = 'light' | 'dark';
Yu's avatar
Yu committed
18

19 20 21 22 23 24 25 26 27 28 29
interface SiderMenuProps {
  menuData: any[];
  location?: H.Location;
  flatMenuKeys?: any[];
  logo?: string;
  collapsed: boolean;
  onCollapse: (collapsed: boolean, type?: CollapseType) => void;
  fixSiderbar?: boolean;
  theme?: SiderTheme;
  isMobile: boolean;
}
jim's avatar
jim committed
30

31 32 33 34
interface SiderMenuState {
  openKeys: any;
  flatMenuKeysLen?: number;
}
Yu's avatar
Yu committed
35

36
export default class SiderMenu extends Component<SiderMenuProps, SiderMenuState> {
jim's avatar
jim committed
37
  static getDerivedStateFromProps(props, state) {
Yu's avatar
Yu committed
38 39
    const { pathname, flatMenuKeysLen } = state;
    if (props.location.pathname !== pathname || props.flatMenuKeys.length !== flatMenuKeysLen) {
jim's avatar
jim committed
40 41
      return {
        pathname: props.location.pathname,
Yu's avatar
Yu committed
42
        flatMenuKeysLen: props.flatMenuKeys.length,
jim's avatar
jim committed
43 44 45 46 47
        openKeys: getDefaultCollapsedSubMenus(props),
      };
    }
    return null;
  }
48 49 50 51 52 53 54 55 56 57
  constructor(props: SiderMenuProps) {
    super(props);
    this.state = {
      openKeys: getDefaultCollapsedSubMenus(props),
    };
  }

  componentDidMount() {
    firstMount = false;
  }
58

59
  isMainMenu: (key: string) => boolean = key => {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
60 61
    const { menuData } = this.props;
    return menuData.some(item => {
jim's avatar
jim committed
62 63 64 65 66
      if (key) {
        return item.key === key || item.path === key;
      }
      return false;
    });
jim's avatar
jim committed
67
  };
68

69
  handleOpenChange: (openKeys: any[]) => void = openKeys => {
ddcat1115's avatar
ddcat1115 committed
70
    const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;
jiang's avatar
jiang committed
71
    this.setState({
jim's avatar
jim committed
72
      openKeys: moreThanOne ? [openKeys.pop()] : [...openKeys],
jiang's avatar
jiang committed
73
    });
74
  };
75

jiang's avatar
jiang committed
76
  render() {
Yu's avatar
Yu committed
77
    const { logo, collapsed, onCollapse, fixSiderbar, theme, isMobile } = this.props;
78
    const { openKeys } = this.state;
jim's avatar
jim committed
79
    const defaultProps = collapsed ? {} : { openKeys };
afc163's avatar
afc163 committed
80 81

    const siderClassName = classNames(styles.sider, {
Yu's avatar
Yu committed
82
      [styles.fixSiderBar]: fixSiderbar,
afc163's avatar
afc163 committed
83 84
      [styles.light]: theme === 'light',
    });
jiang's avatar
jiang committed
85 86
    return (
      <Sider
afc163's avatar
afc163 committed
87
        trigger={null}
88
        collapsible={true}
jiang's avatar
jiang committed
89
        collapsed={collapsed}
90
        breakpoint="lg"
Yu's avatar
Yu committed
91 92 93 94 95
        onCollapse={collapse => {
          if (firstMount || !isMobile) {
            onCollapse(collapse);
          }
        }}
jiang's avatar
jiang committed
96
        width={256}
afc163's avatar
afc163 committed
97 98
        theme={theme}
        className={siderClassName}
jiang's avatar
jiang committed
99
      >
afc163's avatar
afc163 committed
100
        <div className={styles.logo} id="logo">
jiang's avatar
jiang committed
101 102
          <Link to="/">
            <img src={logo} alt="logo" />
Yu's avatar
Yu committed
103
            <h1>{title}</h1>
jiang's avatar
jiang committed
104 105
          </Link>
        </div>
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
106 107 108 109 110 111 112 113 114 115
        <Suspense fallback={<PageLoading />}>
          <BaseMenu
            {...this.props}
            mode="inline"
            handleOpenChange={this.handleOpenChange}
            onOpenChange={this.handleOpenChange}
            style={{ padding: '16px 0', width: '100%' }}
            {...defaultProps}
          />
        </Suspense>
jiang's avatar
jiang committed
116 117 118 119
      </Sider>
    );
  }
}