基本架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* 管理的路由组件
*/
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栏动态生成

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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>
)
}

函数内部实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 方式一
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
}, [])
}

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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进行包装成路由组件。

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

自动展开列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 左侧导航组件
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>
)
}
}