用hooks封装一个跟antd-pro效果一样的侧边导航栏

2,450 阅读2分钟

说明:antd-pro的侧边导航栏带有自动缩放、移动端适配的功能,去看了antd-pro的文档,发现是用了一个layout pro组件,算了自己写一个。

效果图:

使用antd4.x

侧边栏组件:

import React, { Fragment } from 'react'
import { Menu, Drawer, Layout } from 'antd'
import {
    UserOutlined,
    VideoCameraOutlined,
    UploadOutlined,
} from '@ant-design/icons';
import { Link } from 'dva/router';
import style from './index.css'
import PropTypes from 'prop-types'

const { Sider } = Layout;
const NavContent = () => {
    return (
        <Fragment>
            <div className={style.logo} />
            <Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
                <Menu.Item key="1" icon={<UserOutlined />}>
                    <Link to="/admin/index">
                        Index
                        </Link>
                </Menu.Item>
                <Menu.Item key="2" icon={<VideoCameraOutlined />}>
                    <Link to="/admin/tables">
                        Tables
                    </Link>
                </Menu.Item>
                <Menu.Item key="3" icon={<UploadOutlined />}>
                    nav 3
            </Menu.Item>
            </Menu>
        </Fragment>
    )
}


const Nav = ({ isMobile, collapsed, changeCollapsed, width = 256 }) => {
    return (
        <Fragment>
            {
                !isMobile ? <Sider
                    collapsible
                    trigger={null}
                    collapsed={collapsed}
                    width={width}
                    style={{
                        height: '100vh',
                    }}
                    onBreakpoint={broken => {
                        changeCollapsed(broken)
                    }}
                    breakpoint="xl"
                >
                    <NavContent />
                </Sider> :
                    <Drawer
                        placement='left'
                        onClose={() => {
                            changeCollapsed(!0)
                        }}
                        visible={!collapsed}
                        closable={false}
                        bodyStyle={{
                            height: '100vh',
                            padding: 0
                        }}
                    >
                        <Sider
                            width={width}
                            style={{
                                height: '100vh',
                            }}
                        >
                            <NavContent />
                        </Sider>
                    </Drawer>
            }
        </Fragment>
    )
}

Nav.propTypes = {
    isMobile: PropTypes.bool.isRequired,
    collapsed: PropTypes.bool.isRequired,
    changeCollapsed: PropTypes.func.isRequired,
    width: PropTypes.number
}

export default Nav
参数 说明
"isMobile" 是否为移动端
"collapsed" 是否折叠
"changeCollapsed" func 改变折叠状态的回调
"width" 侧边栏展示的宽度

如果是移动端的话,则展示抽屉+侧边栏内容,如果页面大小太闲则折叠导航条,功能和antd-pro一致

使用方法:(hooks)

import React, { useState, useEffect } from 'react'
import { Layout } from 'antd';
import {
    MenuUnfoldOutlined,
    MenuFoldOutlined,
} from '@ant-design/icons';
import style from './index.css'
import Index from '../../routes/Index'
import Tables from '../../routes/Tables'
import { Route } from 'dva/router';
import Nav from '../../components/Nav'
const { Header, Content } = Layout;
const Admin = () => {
    const [collapsed, setCollapsed] = useState(false)
    const [isMobile, setIsMobile] = useState(false)
    const handleResize = () => {
        document.documentElement.clientWidth < 768
            ? setIsMobile(true)
            : setIsMobile(false)
    }
    useEffect(() => {
        handleResize()
        window.onresize = handleResize
        return () => {
            window.onresize = null
        }
    }, [])
    return (
        <Layout>
            <Nav
                collapsed={collapsed}
                isMobile={isMobile}
                changeCollapsed={(broken) => setCollapsed(broken)}
            />
            <Layout className="site-layout">
                <Header style={{ padding: 0, backgroundColor: '#ffffff' }}>
                    {React.createElement(collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
                        className: style.trigger,
                        onClick: () => {
                            setCollapsed(!collapsed)
                        },
                    })}
                </Header>
                <Content
                    style={{
                        margin: '24px 16px',
                        padding: 24,
                        minHeight: 280,
                        backgroundColor: '#ffffff'
                    }}
                >
                    <Route path="/admin/index" component={Index} />
                    <Route path="/admin/tables" component={Tables} />
                </Content>
            </Layout>
        </Layout>
    )
}
export default Admin

使用的时候用effect监听一个页面窗口来改变状态,并把所需要的参数都传递给nav就行了

打完收工~