React 项目启动之路由搭建+antDesign实现管理系统Header+Sider布局

目录规范:

1. 子组件都存放在components>父名文件夹中,例如components>sandbox>SideMenu.js

2. 页面级组件(带路由)都存放在views>父名文件夹中,例如views>sandbox>NewsSandBox.js;若有NewsSandBox组件中的页面级组件,就在sandbox下再创建文件夹放入,例如views>sandbox>home>home.js

路由模块安装指令:cnpm i --save-dev react-router-dom@5.2.0

src > App.js

import React from 'react'
import IndexRouter from './router/IndexRouter';
import './App.css'

function App() {
  return <IndexRouter></IndexRouter>

}

export default App;

src > router > IndexRouter.js

import React from 'react'
import { HashRouter, Route, Switch, Redirect } from 'react-router-dom'
import Login from '../views/login/Login'
import NewsSandBox from '../views/sandbox/NewsSandBox'

export default function IndexRouter() {
  return (
    <HashRouter>
      <Switch>
        {/* 制定规则 */}
        <Route path="/login" component={Login} />
        {/* 制定规则 如果存过token 就显示NewsSandBox页面 否则重定向去login页面*/}
        <Route path="/" render={() =>
          localStorage.getItem("token") ?
            <NewsSandBox></NewsSandBox> :
            <Redirect to="/login" />
        } />
      </Switch>
    </HashRouter>
  )
}

src > views > sandbox > NewsSandBox.js

import React from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import SideMenu from '../../components/sandbox/SideMenu'
import TopHeader from '../../components/sandbox/TopHeader'
import Home from './home/Home'
import NoPermission from './nopermission/NoPermission'
import RightList from './right-manage/RightList'
import RoleList from './right-manage/RoleList'
import UserList from './user-manage/UserList'

export default function NewsSandBox() {
  return (
    <div>
      <SideMenu></SideMenu>
      <TopHeader></TopHeader>
      <Switch>
        {/* 制定规则 如果走的是以下预约的4个路径... */}
        <Route path="/home" component={Home} />
        <Route path="/user-manage/list" component={UserList} />
        <Route path="/right-manage/role/list" component={RoleList} />
        <Route path="/right-manage/right/list" component={RightList} />

        {/* 制定规则 如果不加exact 那么任何带有/的路径都会被带到/home */}
        <Redirect from="/" to="/home" exact />
        {/* 和上一行搭配使用——如果你走的不是我们预定好的路由... */}
        <Route path="*" component={NoPermission} />
      </Switch>
    </div>
  )
}

=============================使用antd后==============================

src > App.css

@import '~antd/dist/antd.css';

src > views > sandbox > NewsSandBox.js

import React from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import SideMenu from '../../components/sandbox/SideMenu'
import TopHeader from '../../components/sandbox/TopHeader'
import Home from './home/Home'
import NoPermission from './nopermission/NoPermission'
import RightList from './right-manage/RightList'
import RoleList from './right-manage/RoleList'
import UserList from './user-manage/UserList'
//css
import './NewsSandBox.css'
//antd
import { Layout } from 'antd';
const { Content } = Layout;

export default function NewsSandBox() {
  return (
    <Layout>
      <SideMenu></SideMenu>
      <Layout className="site-layout">
        <TopHeader></TopHeader>
        <Content
          className="site-layout-background"
          style={{
            margin: '24px 16px',
            padding: 24,
            minHeight: 280,
          }}
        >
          <Switch>
            {/* 制定规则 如果走的是以下预约的4个路径... */}
            <Route path="/home" component={Home} />
            <Route path="/user-manage/list" component={UserList} />
            <Route path="/right-manage/role/list" component={RoleList} />
            <Route path="/right-manage/right/list" component={RightList} />

            {/* 制定规则 如果不加exact 那么任何带有/的路径都会被带到/home */}
            <Redirect from="/" to="/home" exact />
            {/* 和上一行搭配使用——如果你走的不是我们预定好的路由... */}
            <Route path="*" component={NoPermission} />
          </Switch>
        </Content>
      </Layout>
    </Layout>
  )
}

src > views > sandbox > NewsSandBox.css

#components-layout-demo-custom-trigger .trigger {
  padding: 0 24px;
  font-size: 18px;
  line-height: 64px;
  cursor: pointer;
  transition: color 0.3s;
}

#components-layout-demo-custom-trigger .trigger:hover {
  color: #1890ff;
}

#components-layout-demo-custom-trigger .logo {
  height: 32px;
  margin: 16px;
  background: rgba(255, 255, 255, 0.3);
}

.site-layout .site-layout-background {
  background: #fff;
}

/* 高为100%占满屏幕 */
#root,.ant-layout{
  height: 100%;
}

src > components > sandbox > SideMenu.js

import React, { useEffect, useState } from 'react'
import { Layout, Menu } from 'antd';
import './index.css';
import { withRouter } from 'react-router-dom';
import {
  UserOutlined,
  VideoCameraOutlined,
  UploadOutlined,
  SettingOutlined
} from '@ant-design/icons';
import axios from 'axios';
const { Sider } = Layout;
const { SubMenu } = Menu;

//模拟数组解构 现已无用
// const menuList = [
//   {
//     key: '/home',//只是用做key值
//     title: '首页',
//     icon: <UserOutlined />
//   },
//   {
//     key: '/user-manage',//只是用做key值
//     title: '用户管理',
//     icon: <VideoCameraOutlined />,
//     children: [
//       {
//         key: '/user-manage/list',//只是用做key值
//         title: '用户列表',
//         icon: <VideoCameraOutlined />,
//       }
//     ]
//   },
//   {
//     key: '/right-manage',//只是用做key值
//     title: '权限管理',
//     icon: <UploadOutlined />,
//     children: [
//       {
//         key: '/right-manage/role/list',//只是用做key值
//         title: '角色列表',
//         icon: <UploadOutlined />,
//       },
//       {
//         key: '/right-manage/right/list',//只是用做key值
//         title: '权限列表',
//         icon: <UploadOutlined />,
//       },
//     ]
//   },
// ]

//前端定义iconList
const iconList = {
  '/home': <UserOutlined />,
  '/user-manage': <VideoCameraOutlined />,
  '/user-manage/list': <VideoCameraOutlined />,
  '/right-manage': <UploadOutlined />,
  '/right-manage/role/list': <UploadOutlined />,
  '/right-manage/right/list': <SettingOutlined />
}

function SideMenu(props) {
  const [menu, setMenu] = useState([])
  //改从后端获取路由数组
  useEffect(() => {
    axios.get('http://localhost:3000/rights?_embed=children').then(
      res => {
        console.log(res.data);
        setMenu(res.data)
      }
    )
  }, [])

  //根据是否item有pagepermisson这个字段决定是否将这个item渲染在侧边栏
  const checkPagePermission = (item) => {
    return item.pagepermisson === 1
  }

  const renderMenu = (menuList) => {
    return menuList.map(item => {
      //item.children?表示:item.children为undefined的话就不继续执行了
      if (item.children?.length > 0 && checkPagePermission(item)) {
        return <SubMenu key={item.key} icon={iconList[item.key]} title={item.title}>
          {renderMenu(item.children)}
        </SubMenu>
      } else {
        return checkPagePermission(item) && <Menu.Item key={item.key} icon={iconList[item.key]}
          onClick={
            () => {
              props.history.push(item.key)
            }
          }>{item.title}</Menu.Item>
      }
    })
  }
  //刷新页面也不改变已选中的侧边栏 defaultSelectedKeys-选中的 defaultOpenKeys-展开并高亮的
  console.log(props.location.pathname);
  const selectedKeys = [props.location.pathname]//  /right-manage/role/list
  const openKeys = ["/" + props.location.pathname.split('/')[1]]//  /right-manage
  return (
    <Sider trigger={null} collapsible collapsed={false} >
      <div style={{ display: "flex", height: "100%", flexDirection: 'column' }}>
        <div className="logo" >全球新闻发布管理系统</div>
        <div style={{ flex: 1, overflow: "auto" }}>
          <Menu theme="dark" mode="inline"
            selectedKeys={selectedKeys}
            defaultOpenKeys={openKeys}
          >
            {/* <Menu.Item key="1" icon={<UserOutlined />}>
          nav 1
        </Menu.Item>
        <Menu.Item key="2" icon={<VideoCameraOutlined />}>
          nav 2
        </Menu.Item>
        <Menu.Item key="3" icon={<UploadOutlined />}>
          nav 3
        </Menu.Item>
        <SubMenu key="sub4" icon={<SettingOutlined />} title="Navigation Three">
          <Menu.Item key="9">Option 9</Menu.Item>
          <Menu.Item key="10">Option 10</Menu.Item>
          <Menu.Item key="11">Option 11</Menu.Item>
          <Menu.Item key="12">Option 12</Menu.Item>
        </SubMenu> */}
            {renderMenu(menu)}
          </Menu>
        </div>
      </div>
    </Sider>
  )
}

export default withRouter(SideMenu)

src > components > sandbox > TopHeader.js

import React, { useState } from 'react'
import { Layout, Avatar } from 'antd';
import {
  MenuUnfoldOutlined,
  MenuFoldOutlined,
  UserOutlined
} from '@ant-design/icons';
import { Menu, Dropdown } from 'antd';
const { Header } = Layout;

export default function TopHeader() {
  const [collapsed, setCollapsed] = useState(false)
  const changeCollapsed = () => {
    setCollapsed(!collapsed)
  }
  const menu = (
    <Menu>
      <Menu.Item key="1">
        超级管理员
      </Menu.Item>
      <Menu.Item key="2" danger>
        退出
      </Menu.Item>
    </Menu>
  );
  return (
    <Header className="site-layout-background" style={{ padding: "0 16px" }}>
      {
        collapsed ?
          <MenuUnfoldOutlined onClick={changeCollapsed} /> :
          <MenuFoldOutlined onClick={changeCollapsed} />
      }
      <div style={{ float: "right" }}>
        <span>欢迎admin</span>
        <Dropdown overlay={menu}>
          <Avatar size="large" icon={<UserOutlined />} />
        </Dropdown>
      </div>
    </Header>
  )
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值