SiderMenu.tsx 3.45 KB
Newer Older
1
import { Layout } from 'antd';
afc163's avatar
afc163 committed
2
import classNames from 'classnames';
3
import React, { Component, Suspense } from 'react';
zinkey's avatar
zinkey committed
4
import Link from 'umi/link';
5
import defaultSettings from '../../../config/defaultSettings';
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
6
import PageLoading from '../PageLoading';
何乐's avatar
何乐 committed
7
import { BaseMenuProps } from './BaseMenu';
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

何乐's avatar
何乐 committed
16
export interface SiderMenuProps extends BaseMenuProps {
17 18 19
  logo?: string;
  fixSiderbar?: boolean;
}
jim's avatar
jim committed
20

21
interface SiderMenuState {
何乐's avatar
何乐 committed
22 23
  pathname?: string;
  openKeys?: string[];
24 25
  flatMenuKeysLen?: number;
}
Yu's avatar
Yu committed
26

27
export default class SiderMenu extends Component<SiderMenuProps, SiderMenuState> {
何乐's avatar
何乐 committed
28 29 30 31 32 33 34 35 36 37 38 39 40
  static defaultProps: SiderMenuProps = {
    flatMenuKeys: [],
    location: window.location,
    onCollapse: () => void 0,
    isMobile: false,
    openKeys: [],
    collapsed: false,
    handleOpenChange: () => void 0,
    menuData: [],
    onOpenChange: () => void 0,
  };

  static getDerivedStateFromProps(props: SiderMenuProps, state: SiderMenuState) {
Yu's avatar
Yu committed
41
    const { pathname, flatMenuKeysLen } = state;
何乐's avatar
何乐 committed
42
    if (props.location!.pathname !== pathname || props.flatMenuKeys!.length !== flatMenuKeysLen) {
jim's avatar
jim committed
43
      return {
何乐's avatar
何乐 committed
44 45
        pathname: props.location!.pathname,
        flatMenuKeysLen: props.flatMenuKeys!.length,
jim's avatar
jim committed
46 47 48 49 50
        openKeys: getDefaultCollapsedSubMenus(props),
      };
    }
    return null;
  }
何乐's avatar
何乐 committed
51

52 53 54 55 56 57 58 59 60 61
  constructor(props: SiderMenuProps) {
    super(props);
    this.state = {
      openKeys: getDefaultCollapsedSubMenus(props),
    };
  }

  componentDidMount() {
    firstMount = false;
  }
62

63
  isMainMenu: (key: string) => boolean = key => {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
64
    const { menuData } = this.props;
何乐's avatar
何乐 committed
65
    return menuData!.some(item => {
jim's avatar
jim committed
66 67 68 69 70
      if (key) {
        return item.key === key || item.path === key;
      }
      return false;
    });
jim's avatar
jim committed
71
  };
72

何乐's avatar
何乐 committed
73
  handleOpenChange: (openKeys: string[]) => void = openKeys => {
ddcat1115's avatar
ddcat1115 committed
74
    const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;
何乐's avatar
何乐 committed
75 76 77 78 79
    if (moreThanOne) {
      this.setState({ openKeys: [openKeys.pop()].filter(item => item) as string[] });
    } else {
      this.setState({ openKeys: [...openKeys] });
    }
80
  };
81

jiang's avatar
jiang committed
82
  render() {
Yu's avatar
Yu committed
83
    const { logo, collapsed, onCollapse, fixSiderbar, theme, isMobile } = this.props;
84
    const { openKeys } = this.state;
jim's avatar
jim committed
85
    const defaultProps = collapsed ? {} : { openKeys };
afc163's avatar
afc163 committed
86 87

    const siderClassName = classNames(styles.sider, {
Yu's avatar
Yu committed
88
      [styles.fixSiderBar]: fixSiderbar,
afc163's avatar
afc163 committed
89 90
      [styles.light]: theme === 'light',
    });
jiang's avatar
jiang committed
91 92
    return (
      <Sider
何乐's avatar
何乐 committed
93
        collapsible
afc163's avatar
afc163 committed
94
        trigger={null}
jiang's avatar
jiang committed
95
        collapsed={collapsed}
96
        breakpoint="lg"
Yu's avatar
Yu committed
97 98
        onCollapse={collapse => {
          if (firstMount || !isMobile) {
何乐's avatar
何乐 committed
99
            onCollapse!(collapse);
Yu's avatar
Yu committed
100 101
          }
        }}
jiang's avatar
jiang committed
102
        width={256}
afc163's avatar
afc163 committed
103 104
        theme={theme}
        className={siderClassName}
jiang's avatar
jiang committed
105
      >
afc163's avatar
afc163 committed
106
        <div className={styles.logo} id="logo">
jiang's avatar
jiang committed
107 108
          <Link to="/">
            <img src={logo} alt="logo" />
Yu's avatar
Yu committed
109
            <h1>{title}</h1>
jiang's avatar
jiang committed
110 111
          </Link>
        </div>
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
112 113 114 115 116 117 118 119 120 121
        <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
122 123 124 125
      </Sider>
    );
  }
}