基本架构

/**
 * 管理的路由组件
 */
import React, { Component } from 'react'
import { Redirect, Route, Switch } from 'react-router-dom'
import { Layout } from 'antd'

import memoryUtils from '../../utils/memoryUtils'
import LeftNav from '../../components/left-nav/left-nav'
import Header from '../../components/header/header'
// 路由组件
import Home from '../home/home'
import Category from '../category/category'
import Product from '../product/product'
import Role from '../role/role'
import User from '../user/user'
// 图表
import Bar from '../charts/bar' // 柱状图
import Line from '../charts/line' // 折线图
import Pie from '../charts/pie' // 饼状图

const { Footer, Sider, Content } = Layout

export default class Admin extends Component {
  render() {
    const user = memoryUtils.user
    // 判断是否存在user
    if (!user || !user._id) {
      // 没有登录,自动跳转
      return <Redirect to='/login' />
    } else {
      return (
        <Layout style={{ height: '100%' }}>
          <Sider>
            <LeftNav />
          </Sider>
          <Layout>
            <Header> Hello {user.username}</Header>
            <Content style={{ backgroundColor: '#fff' }}>
              <Switch>
                <Route path='/home' component={Home} />
                <Route path='/category' component={Category} />
                <Route path='/product' component={Product} />
                <Route path='/role' component={Role} />
                <Route path='/user' component={User} />
                <Route path='/charts/bar' component={Bar} />
                <Route path='/charts/line' component={Line} />
                <Route path='/charts/pie' component={Pie} />
                <Redirect to='/home'></Redirect>
              </Switch>
            </Content>
            <Footer style={{ textAlign: 'center', color: '#ccc' }}>
              推荐使用咕咕浏览器获得极致体验
            </Footer>
          </Layout>
        </Layout>
      )
    }
  }
}

左侧Nav栏动态生成

页面结构:通过一个配置文件动态生成导航栏

render() {
    const path = this.props.location.pathname
    return (
        <div className='left-nav'>
            <Link className='left-nav-header' to='/home'>
                <img src={logo} alt='logo' />
                <h1>谷粒后台</h1>
            </Link>
            <Menu
                selectedKeys={[path]}
                mode='inline'
                theme='dark'
                >
                {this.getMenuNodes(menuList)}
            </Menu>
        </div>
    )
}

函数内部实现

// 方式一
getMenuNodes_map = (menuList) => {
    return menuList.map((item) => {
        if (!item.children) {
            return (
                <Menu.Item key={item.key}>
                    <IconFont type={item.icon} />
                    <Link to={item.key}>{item.title}</Link>
                </Menu.Item>
            )
        } else {
            return (
                <SubMenu
                    key={item.key}
                    title={item.title}
                    icon={<IconFont type={item.icon} />}
                    >
                    {/* 递归调用 */}
                    {this.getMenuNodes(item.children)}
                </SubMenu>
            )
        }
    })
}
// 方式2
getMenuNodes = (menuList) => {
    return menuList.reduce((pre, item) => {
        // 向pre中添加
        if (!item.children) {
            pre.push(
                <Menu.Item key={item.key}>
                    <IconFont type={item.icon} />
                    <Link to={item.key}>{item.title}</Link>
                </Menu.Item>
            )
        } else {
            pre.push(
                <SubMenu
                    key={item.key}
                    title={item.title}
                    icon={<IconFont type={item.icon} />}
                    >
                    {/* 递归调用 */}
                    {this.getMenuNodes(item.children)}
                </SubMenu>
            )
        }
        return pre
    }, [])
}

配置文件

const menuList = [
    {
        title: '首页', // 菜单标题名称
        key: '/home', // 对应的path
        icon: 'icon-index-0-copy', // 图标名称
    },
    {
        title: '商品',
        key: '/products',
        icon: 'icon-shangpin',
        children: [ // 子菜单列表
            {
                title: '品类管理',
                key: '/category',
                icon: 'icon-leimupinleifenleileibie'
            },
            {
                title: '商品管理',
                key: '/product',
                icon: 'icon-guanli'
            },
        ]
    },
    {
        title: '用户管理',
        key: '/user',
        icon: 'icon-yonghu'
    },
    {
        title: '角色管理',
        key: '/role',
        icon: 'icon-jiaose',
    },
    {
        title: '图形图表',
        key: '/charts',
        icon: 'icon-biaoge',
        children: [
            {
                title: '柱形图',
                key: '/charts/bar',
                icon: 'icon-tubiaozhuxingtu'
            },
            {
                title: '折线图',
                key: '/charts/line',
                icon: 'icon-tubiaoxian_tongyong_tongji'
            },
            {
                title: '饼图',
                key: '/charts/pie',
                icon: 'icon-tubiao08'
            },
        ]
    },
]
export default menuList

获取当前页面地址

通过withRouter进行包装成路由组件。

import { withRouter } from 'react-router-dom'
class LeftNav extends Component {}
// 通过使用withRouter包装获取路由
export default withRouter(LeftNav)

自动展开列表

// 左侧导航组件
class LeftNav extends Component {
  constructor(props) {
    super(props)
    this.menuNodes = this.getMenuNodes(menuList)
  }
  getMenuNodes = (menuList) => {
    const path = this.props.location.pathname
    return menuList.reduce((pre, item) => {
      // 向pre中添加
      if (!item.children) {
        pre.push(
          <Menu.Item key={item.key}>
            <IconFont type={item.icon} />
            <Link to={item.key}>{item.title}</Link>
          </Menu.Item>
        )
      } else {
        const cItem = item.children.find((cItem) => cItem.key === path)
        // 如果存在
        if (cItem) this.openKey = item.key

        pre.push(
          <SubMenu
            key={item.key}
            title={item.title}
            icon={<IconFont type={item.icon} />}
          >
            {/* 递归调用 */}
            {this.getMenuNodes(item.children)}
          </SubMenu>
        )
      }
      return pre
    }, [])
  }
  render() {
    const path = this.props.location.pathname
    // 需要打开菜单的key
    const openKey = this.openKey

    return (
      <div className='left-nav'>
        <Link className='left-nav-header' to='/home'>
          <img src={logo} alt='logo' />
          <h1>谷粒后台</h1>
        </Link>
        <Menu
          selectedKeys={[path]}
          defaultOpenKeys={[openKey]}
          mode='inline'
          theme='dark'
        >
          {this.menuNodes}
        </Menu>
      </div>
    )
  }
}