Skip to content

Commit

Permalink
refactor: refact Sider by hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
yezihaohao committed Sep 13, 2020
1 parent 196dfea commit cd2e7ad
Show file tree
Hide file tree
Showing 5 changed files with 13,688 additions and 13,655 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@types/recharts": "^1.1.21",
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.9.1",
"ahooks": "^2.6.0",
"antd": "^3.23.5",
"axios": "^0.19.0",
"babel-eslint": "10.0.3",
Expand Down
6 changes: 3 additions & 3 deletions src/components/HeaderCustom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type HeaderCustomProps = {
const HeaderCustom = (props: HeaderCustomProps) => {
const [user, setUser] = useState<any>();
const [responsive] = useAlita('responsive', { light: true });
const [visible, turnOn, turnOff] = useSwitch();
const [visible, turn] = useSwitch();
const history = useHistory();

useEffect(() => {
Expand Down Expand Up @@ -67,11 +67,11 @@ const HeaderCustom = (props: HeaderCustomProps) => {
<Header className="custom-theme header">
{responsive?.isMobile ? (
<Popover
content={<SiderCustom popoverHide={turnOff} />}
content={<SiderCustom popoverHide={turn.turnOff} />}
trigger="click"
placement="bottomLeft"
visible={visible}
onVisibleChange={(visible) => (visible ? turnOn() : turnOff())}
onVisibleChange={(visible) => (visible ? turn.turnOn() : turn.turnOff())}
>
<Icon type="bars" className="header__trigger custom-trigger" />
</Popover>
Expand Down
160 changes: 72 additions & 88 deletions src/components/SiderCustom.tsx
Original file line number Diff line number Diff line change
@@ -1,119 +1,103 @@
/**
* Created by hao.cheng on 2017/4/13.
*/
import React, { Component } from 'react';
import React, { useState, useEffect } from 'react';
import { Layout } from 'antd';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import routes from '../routes/config';
import SiderMenu from './SiderMenu';
import { connectAlita } from 'redux-alita';

import { useAlita } from 'redux-alita';
import { useSwitch } from '../utils/hooks';
import { usePrevious } from 'ahooks';
const { Sider } = Layout;

type SiderCustomProps = RouteComponentProps<any> & {
popoverHide?: () => void;
collapsed?: boolean;
smenus?: any;
};
type SiderCustomState = {
collapsed?: boolean | undefined;
interface IMenu {
openKeys: string[];
firstHide: boolean | undefined;
selectedKey: string;
mode: string;
};
}

const SiderCustom = (props: SiderCustomProps) => {
const [collapsed, tCollapsed] = useSwitch();
const [firstHide, tFirstHide] = useSwitch();
const [menu, setMenu] = useState<IMenu>({ openKeys: [''], selectedKey: '' });
// 异步菜单
const [smenus] = useAlita({ smenus: [] }, { light: true });
const { location, collapsed: pCollapsed } = props;
const prePathname = usePrevious(props.location.pathname);

class SiderCustom extends Component<SiderCustomProps, SiderCustomState> {
constructor(props: any) {
super(props);
this.state = {
mode: 'inline',
openKeys: [],
selectedKey: '',
firstHide: false, // 点击收缩菜单,第一次隐藏展开子菜单,openMenu时恢复
useEffect(() => {
const recombineOpenKeys = (openKeys: string[]) => {
let i = 0;
let strPlus = '';
let tempKeys: string[] = [];
// 多级菜单循环处理
while (i < openKeys.length) {
strPlus += openKeys[i];
tempKeys.push(strPlus);
i++;
}
return tempKeys;
};
const getOpenAndSelectKeys = () => {
return {
openKeys: recombineOpenKeys(location.pathname.match(/[/](\w+)/gi) || []),
selectedKey: location.pathname,
};
};
}

componentDidUpdate(prevProps: SiderCustomProps) {
if (this.props.collapsed !== this.state.collapsed) {
const { collapsed } = this.props;
this.setState({
...this.getOpenAndSelectKeys(),
collapsed,
mode: collapsed ? 'vertical' : 'inline',
firstHide: collapsed,
});
}
if (prevProps.location.pathname !== this.props.location.pathname) {
this.setState({ ...this.getOpenAndSelectKeys() });
if (pCollapsed !== collapsed) {
setMenu(getOpenAndSelectKeys());
tCollapsed.setSwitcher(!!pCollapsed);
tFirstHide.setSwitcher(!!pCollapsed);
}
}

getOpenAndSelectKeys() {
const { location } = this.props;
const { pathname } = location;
return {
openKeys: this.recombineOpenKeys(pathname.match(/[/](\w+)/gi) || []),
selectedKey: pathname,
};
}

recombineOpenKeys = (openKeys: string[]) => {
let i = 0;
let strPlus = '';
let tempKeys: string[] = [];
while (i < openKeys.length) {
strPlus += openKeys[i];
tempKeys.push(strPlus);
i++;
if (prePathname !== location.pathname) {
setMenu(getOpenAndSelectKeys());
}
return tempKeys;
};
}, [prePathname, location.pathname, collapsed, tFirstHide, tCollapsed, pCollapsed]);

menuClick = (e: any) => {
this.setState({
selectedKey: e.key,
});
const { popoverHide } = this.props; // 响应式布局控制小屏幕点击菜单时隐藏菜单操作
popoverHide && popoverHide();
const menuClick = (e: any) => {
setMenu((state) => ({ ...state, selectedKey: e.key }));
props.popoverHide?.(); // 响应式布局控制小屏幕点击菜单时隐藏菜单操作
};
openMenu = (v: string[]) => {
this.setState({
openKeys: v,
firstHide: false,
});

const openMenu = (v: string[]) => {
setMenu((state) => ({ ...state, openKeys: v }));
tFirstHide.turnOff();
};
render() {
const { selectedKey, openKeys, firstHide, collapsed } = this.state;
const { smenus } = this.props;
return (
<Sider
trigger={null}
breakpoint="lg"
collapsed={collapsed}
style={{ overflowY: 'auto' }}
className="sider-custom"
>
<div className="logo" />
<SiderMenu
menus={[...routes.menus, ...smenus.data]}
onClick={this.menuClick}
mode="inline"
selectedKeys={[selectedKey]}
openKeys={firstHide ? [] : openKeys}
onOpenChange={this.openMenu}
/>
<style>
{`

return (
<Sider
trigger={null}
breakpoint="lg"
collapsed={collapsed}
style={{ overflowY: 'auto' }}
className="sider-custom"
>
<div className="logo" />
<SiderMenu
menus={[...routes.menus, ...smenus]}
onClick={menuClick}
mode="inline"
selectedKeys={[menu.selectedKey]}
openKeys={firstHide ? [] : menu.openKeys}
onOpenChange={openMenu}
/>
<style>
{`
#nprogress .spinner{
left: ${collapsed ? '70px' : '206px'};
right: 0 !important;
}
`}
</style>
</Sider>
);
}
}
</style>
</Sider>
);
};

export default connectAlita([{ smenus: [] }])(withRouter(SiderCustom));
export default withRouter(SiderCustom);
9 changes: 7 additions & 2 deletions src/utils/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
*/
import { useState } from 'react';

interface ITurn {
turnOn: () => void;
turnOff: () => void;
setSwitcher: React.Dispatch<React.SetStateAction<boolean>>;
}
/**
* 布尔开关
* @param init
*/
export function useSwitch(init: boolean = false): [boolean, () => void, () => void] {
export function useSwitch(init: boolean = false): [boolean, ITurn] {
const [switcher, setSwitcher] = useState(init);
const turnOn = () => setSwitcher(true);
const turnOff = () => setSwitcher(false);
return [switcher, turnOn, turnOff];
return [switcher, { turnOn, turnOff, setSwitcher }];
}
Loading

0 comments on commit cd2e7ad

Please sign in to comment.