create-react-app my_eactapp
启动项目
npm start
下载路由插件
npm i react-router-dom@6.22.2```
项目基本框架
创建需要的路由文件,不管先后顺序,根据自己需求创建
我创建的是在srl下创建router文件夹编辑路由
在src下创建pages文件夹保存页面
src/router/indx.js
所以我就需要以下这几个页面
import { createBrowserRouter ,Navigate} from "react-router-dom"
import Main from '../pages/main'
import Home from "../pages/home"
import User from "../pages/user"
import Data from "../pages/data"
// import System from "../pages/system"
import System_info from "../pages/system/system_info"
const routes =[
{
path:'/',
Component:Main,
children:[
// 重定向
{
path:'/',
element:<Navigate to='home' replace></Navigate>
},
{
path:'home',
Component:Home
},
{
path:'user',
Component:User
},
{
path:'data',
Component:Data
},
{
path:'system',
// Component:System,
children:[
{
path:"system_info",
Component:System_info
}
]
}
]
}
]
export default createBrowserRouter(routes)
src/pages/main.js(主入口)
import React from "react";
import { Outlet } from "react-router-dom";
const Main =()=>{
return (
<div>
Main
<Outlet></Outlet>
</div>
)
}
export default Main
src/pages/home/index.js
import React from "react";
const Home =()=>{
return(
<div>
Home页面
</div>
)
}
export default Home
src/pages/data/index.js
import React from "react";
const Data=()=>{
return(
<div>
Data 页面
</div>
)
}
export default Data
src/pages/user/index.js
import React from "react";
const User=()=>{
return(
<div>User页面</div>
)
}
export default User
src/pages/system/system_info/index.js
import React from "react";
const System_info=()=>{
return(
<div>
system_info 页面
</div>
)
}
export default System_info
配置app.js文件
APP.js
import './App.css';
import { RouterProvider } from 'react-router-dom';
import router from './router';
function App() {
return (
<div className='app'>
<RouterProvider router={router}/>
</div>
);
}
export default App;
引入antdesigin
下载antdesigin
npm i antd
npm i @ant-design/icons
导入layout组件
src/pages/main.js(主入口)
import React ,{useState}from "react";
import { Outlet } from "react-router-dom";
// 引入antdesign
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
UploadOutlined,
UserOutlined,
VideoCameraOutlined,
} from '@ant-design/icons';
import { Button, Layout, Menu, theme } from 'antd';
const { Header, Sider, Content } = Layout;
const Main =()=>{
// return (
// <div>
// Main
// <Outlet></Outlet>
// </div>
// )
const [collapsed, setCollapsed] = useState(false);
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
return (
<Layout>
<Sider trigger={null} collapsible collapsed={collapsed}>
<div className="demo-logo-vertical" />
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['1']}
items={[
{
key: '1',
icon: <UserOutlined />,
label: 'nav 1',
},
{
key: '2',
icon: <VideoCameraOutlined />,
label: 'nav 2',
},
{
key: '3',
icon: <UploadOutlined />,
label: 'nav 3',
},
]}
/>
</Sider>
<Layout>
<Header
style={{
padding: 0,
background: colorBgContainer,
}}
>
<Button
type="text"
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={() => setCollapsed(!collapsed)}
style={{
fontSize: '16px',
width: 64,
height: 64,
}}
/>
</Header>
<Content
style={{
margin: '24px 16px',
padding: 24,
minHeight: 280,
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
>
Content
</Content>
</Layout>
</Layout>
);
}
export default Main
修改默认样式
index.css
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
box-sizing: border-box;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
a, a:hover{
color: inherit;
text-decoration: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
html, body {
width: 100%;
/* height: 100%; */
background-color: #f5f5f5;
font-family: 'PingFangSC-Light', 'PingFang SC', 'STHeitiSC-Light', 'Helvetica-Light', 'Arial', 'sans-serif';
}
.fl{
float: left;
}
.fr{
float: right;
.button-group-item{
padding-left: 3px;
}
}
.clearfix{
zoom:1;
&:after{
display:block;
clear:both;
content:"";
visibility: hidden;
height:0;
}
}
.main-container {
min-height: calc(100vh - 64px)
}
.main-container .app-name {
background-color: #001529;
text-align: center;
color: #fff;
line-height: 64px;
font-weight: bold;
font-size: 16px;
}
给组件内添加样式
src/page/main.js
import React ,{useState}from "react";
import { Outlet } from "react-router-dom";
// 引入antdesign
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
UploadOutlined,
UserOutlined,
VideoCameraOutlined,
} from '@ant-design/icons';
import { Button, Layout, Menu, theme } from 'antd';
const { Header, Sider, Content } = Layout;
const Main =()=>{
// return (
// <div>
// Main
// <Outlet></Outlet>
// </div>
// )
const [collapsed, setCollapsed] = useState(false);
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
return (
<Layout className="main-container">
<Sider trigger={null} collapsible collapsed={collapsed}>
<h3 className="app-name"> 通用后台管理</h3>
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['1']}
items={[
{
key: '1',
icon: <UserOutlined />,
label: 'nav 1',
},
{
key: '2',
icon: <VideoCameraOutlined />,
label: 'nav 2',
},
{
key: '3',
icon: <UploadOutlined />,
label: 'nav 3',
},
]}
style={{
height:'100%'
}}
/>
</Sider>
<Layout>
<Header
style={{
padding: 0,
background: colorBgContainer,
}}
>
<Button
type="text"
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={() => setCollapsed(!collapsed)}
style={{
fontSize: '16px',
width: 64,
height: 64,
}}
/>
</Header>
<Content
style={{
margin: '24px 16px',
padding: 24,
minHeight: 280,
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
>
Content
</Content>
</Layout>
</Layout>
);
}
export default Main
main.js拆分组件
拆aside组件
拆分main.js组件中的aside组件- 1 创建src/compontens/co
mpontentAside/index.js 将需要用到的Aside组件需要的代码以及包导入
将组件通信代码先去掉,因为组件之间的调用变化了,也就是
icon={collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
onClick={() => setCollapsed(!collapsed)}
的相关代码先去掉
rc/compontens/compontentAside/index.js
import React from "react";
import {
UploadOutlined,
UserOutlined,
VideoCameraOutlined,
} from '@ant-design/icons';
import { Layout, Menu } from 'antd';
const { Sider } = Layout;
const ConmonAside=()=>{
return(
<Sider trigger={null} collapsible >
<h3 className="app-name"> 通用后台管理</h3>
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['1']}
items={[
{
key: '1',
icon: <UserOutlined />,
label: 'nav 1',
},
{
key: '2',
icon: <VideoCameraOutlined />,
label: 'nav 2',
},
{
key: '3',
icon: <UploadOutlined />,
label: 'nav 3',
},
]}
style={{
height:'100%'
}}
/>
</Sider>
)
}
export default ConmonAside
2 - 然后将该aside组件导入在main,js中
src/pages/main.js
import React from "react";
import { Outlet } from "react-router-dom";
// 引入antdesign
// import {
// MenuFoldOutlined,
// MenuUnfoldOutlined,
// UploadOutlined,
// UserOutlined,
// VideoCameraOutlined,
// } from '@ant-design/icons';
import { Button, Layout, theme } from 'antd';
import ConmonAside from "../compontents/componentAside";
const { Header, Content } = Layout;
const Main =()=>{
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();
return (
<Layout className="main-container">
<ConmonAside/>
<Layout>
<Header
style={{
padding: 0,
background: colorBgContainer,
}}
>
<Button
type="text"
style={{
fontSize: '16px',
width: 64,
height: 64,
}}
/>
</Header>
<Content
style={{
margin: '24px 16px',
padding: 24,
minHeight: 280,
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
>
Content
</Content>
</Layout>
</Layout>
);
}
export default Main
3 -创建路由配置文件
src/config/index.js
export default [
{
path: '/home',
name: 'home',
label: '首页',
icon: 'HomeOutlined',
url: '/home/index'
},
{
path: '/mall',
name: 'mall',
label: '商品管理',
icon: 'ShopOutlined',
url: '/mall/index'
},
{
path: '/user',
name: 'user',
label: '用户管理',
icon: 'UserOutlined',
url: '/user/index'
},
{
path: '/other',
label: '其他',
icon: 'SettingOutlined',
children: [
{
path: '/other/pageOne',
name: 'page1',
label: '页面1',
icon: 'SettingOutlined'
},
{
path: '/other/pageTwo',
name: 'page2',
label: '页面2',
icon: 'SettingOutlined'
}
]
}
]
编辑asidey的index.js更改动态路由
rc/compontens/compontentAside/index.js
import React, { lazy } from "react";
import MenuConfig from '../../config'
import * as Icon from '@ant-design/icons'; //取别名
import { Layout, Menu } from 'antd';
const { Sider } = Layout;
//动态获取icon。将icon处理成react组件,因为antdesign是这样处理的
const iconToElement = (name)=> React.createElement(Icon[name])
//处理菜单数据
const items = MenuConfig.map((icon)=>{
//没有子菜单
const child = {
key:icon.path,
icon:iconToElement(icon.icon),
label:icon.label
}
//有子菜单
if (icon.children){
child.children = icon.children.map(item=>{
return{
key:item.path,
label:item.label
}
})
}
return child
})
const ConmonAside=()=>{
return(
<Sider trigger={null} collapsible >
<h3 className="app-name"> 通用后台管理</h3>
<Menu
theme="dark"
mode="inline"
defaultSelectedKeys={['1']}
items={items}
style={{
height:'100%'
}}
/>
</Sider>
)
}
export default ConmonAside
效果展示
拆header组件
1 - 将header组要的代码以及包移动到src/compontens/conpontentHeader/index.js中
1.1实现header图标和收缩菜单的位置的设置,点击都想有下拉菜单的功能
src/compontens/conpontentHeader/index.js
import React from "react";
import { Layout,Avatar,Button,Dropdown } from "antd";
import { MenuFoldOutlined } from "@ant-design/icons";
import './index.css'
const {Header} = Layout
const ConmonHeader=()=>{
const logout=()=>{
alert("退出登录")
}
const items=[
{
key:'1',
label:(
<a target="_blank" rel="noopenner noreferrer">个人中心</a>
),
},
{
key:'1',
label:(
<a onClick={ ()=> logout} target="_blank" rel="noopenner noreferrer">退出</a>
),
}
]
return(
<Header className="header-container">
<Button
type="text"
icon={<MenuFoldOutlined/>}
style={{
fontSize:'16px',
width:64,
height:32,
backgroundColor:'#fff'
}}/>
<Dropdown
menu={{items}}
>
<Avatar size={36} src={ <img src={require("../../assets/images/user.png")}/>} />
</Dropdown>
</Header>
)
}
export default ConmonHeader
src/compontens/conpontentHeader/index.css
/* 头像和收缩图标分布左右上线剧中 */
.header-container{
display: flex;
justify-content: space-between;
align-items: center;
}
src/assets/images/下添加头像的图片