react + antd 实现后台管理系统

文章目录

            • 完整路由搭建
            • Layout 和 Aside组件引入 Antd
            • Aside组件实现


项目效果图
在这里插入图片描述
在这里插入图片描述

项目完整代码地址

https://gitee.com/lyh1999/react-back-management
项目完整代码地址

react依赖安装 最好采用yarn 安装

react-router 安装依赖

配置路由

history模式 /

// src/router/index.jsx
import { createBrowserRouter } from "react-router-dom";
import Home from "../views/Home";
import Login from "../views/Login";const router = createBrowserRouter([{path:'/',element: <Home />,},{path:'/login',element: <Login />,}
])export default router

hash模式 #

// src/router/index.jsx
import { createHashRouter } from "react-router-dom";
import Home from "../views/Home";
import Login from "../views/Login";const router = createHashRouter([{path: "/",element: <Home />,},{path: "/login",element: <Login />,},
]);export default router;

basename 设置子路由的前缀

创建router路由文件

import { createBrowserRouter } from "react-router-dom";
import Main from "../pages/main";
import Home from "../pages/home";const routes = [{path: "/",Component: Main,children: [{path: "/home",Component: Home,}],},
];export default createBrowserRouter(routes);

创建main.js main组件 这里可以挂载子路由出口Outlet

import React from 'react'
// 引入子路由出口
import {Outlet} from 'react-router-dom'const Main = () => {return (<div><h1>main</h1><Outlet/></div>)
}export default Main

创建子路由home组件

import React from "react";import './home.css'
const Home = () => {return (<div><h1>Home</h1></div>);
}export default Home;

App.js挂载路由router RouterProvider

import "./App.css";
import { RouterProvider } from "react-router-dom";
import router from "./router/index";function App() {return (<div className="App"><RouterProvider router={router} /></div>);
}export default App;

导入完整路由组件

import { createBrowserRouter } from "react-router-dom";
import Main from "../pages/main";
import Home from "../pages/home";
import Mall from "../pages/mall";
import User from "../pages/user";const routes = [{path: "/",Component: Main,children: [{path: "/home",Component: Home,},{path: "/user",Component: User,},{path: "/mall",Component: Mall,}],},
];export default createBrowserRouter(routes);

改为懒加载

import { createBrowserRouter, lazy, Suspense } from "react-router-dom";
import Main from "../pages/main"; // 主布局组件可以提前加载// 使用 React.lazy 动态导入组件
const Home = lazy(() => import("../pages/home"));
const Mall = lazy(() => import("../pages/mall"));
const User = lazy(() => import("../pages/user"));const routes = [{path: "/",element: <Main />,children: [{path: "home", // 注意:子路由路径不需要以斜杠开头element: (<Suspense fallback={<div>Loading...</div>}><Home /></Suspense>),},{path: "user",element: (<Suspense fallback={<div>Loading...</div>}><User /></Suspense>),},{path: "mall",element: (<Suspense fallback={<div>Loading...</div>}><Mall /></Suspense>),},],},
];export default createBrowserRouter(routes);

添加完整路由组件 mall user pageOne pageTwo

完整路由搭建

代码

import { createBrowserRouter, Navigate } from "react-router-dom";
import { Suspense, lazy } from "react";
import Main from "../pages/main"; // 主布局组件可以提前加载// 使用 React.lazy 动态导入组件
const Home = lazy(() => import("../pages/home"));
const Mall = lazy(() => import("../pages/mall"));
const User = lazy(() => import("../pages/user"));
const PageTwo = lazy(() => import("../pages/other/pageTwo"));
const PageOne = lazy(() => import("../pages/other/pageOne"));const routes = [{path: "/",element: <Main />,children: [// 路由重定向{path: "/",element: <Navigate to={"/home"} replace />,},{path: "home", // 注意:子路由路径不需要以斜杠开头element: (<Suspense fallback={<div>Loading...</div>}><Home /></Suspense>),},{path: "user",element: (<Suspense fallback={<div>Loading...</div>}><User /></Suspense>),},{path: "mall",element: (<Suspense fallback={<div>Loading...</div>}><Mall /></Suspense>),},{path: "other",children:[{path: "pageOne",element: (<Suspense fallback={<div>Loading...</div>}><PageOne /></Suspense>)},{path: "pageTwo",element: (<Suspense fallback={<div>Loading...</div>}><PageTwo /></Suspense>)}]}],},
];export default createBrowserRouter(routes);
Layout 和 Aside组件引入 Antd
npm install antd

复制官网的Layout 代码到main.js

import React, { useState } from "react";
// 引入子路由出口
import { Outlet } from "react-router-dom";
import {DesktopOutlined,FileOutlined,PieChartOutlined,TeamOutlined,UserOutlined,
} from "@ant-design/icons";
import { Breadcrumb, Layout, Menu, theme } from "antd";
const { Header, Content, Footer, Sider } = Layout;const items = [getItem("Option 1", "1", <PieChartOutlined />),getItem("Option 2", "2", <DesktopOutlined />),getItem("User", "sub1", <UserOutlined />, [getItem("Tom", "3"),getItem("Bill", "4"),getItem("Alex", "5"),]),getItem("Team", "sub2", <TeamOutlined />, [getItem("Team 1", "6"),getItem("Team 2", "8"),]),getItem("Files", "9", <FileOutlined />),
];function getItem(label, key, icon, children) {return {key,icon,                 children,label,};
}const Main = () => {const [collapsed, setCollapsed] = useState(false);const {token: { colorBgContainer, borderRadiusLG },} = theme.useToken();return (<Layout style={{ minHeight: "100vh" }}><Sidercollapsiblecollapsed={collapsed}onCollapse={(value) => setCollapsed(value)}><div className="demo-logo-vertical" /><Menutheme="dark"defaultSelectedKeys={["1"]}mode="inline"items={items}/></Sider><Layout><Header style={{ padding: 0, background: colorBgContainer }} /><Content style={{ margin: "0 16px" }}><Breadcrumb style={{ margin: "16px 0" }}><Breadcrumb.Item>User</Breadcrumb.Item><Breadcrumb.Item>Bill</Breadcrumb.Item></Breadcrumb><divstyle={{padding: 24,minHeight: 360,background: colorBgContainer,borderRadius: borderRadiusLG,}}>Bill is a cat.</div></Content><Footer style={{ textAlign: "center" }}>Ant Design ©{new Date().getFullYear()} Created by Ant UED</Footer></Layout></Layout>);
};export default Main;

组件抽离 将side组件抽取出来

import React, { useState } from "react";
import { Layout, Menu } from "antd";
import {DesktopOutlined,FileOutlined,PieChartOutlined,TeamOutlined,UserOutlined,
} from "@ant-design/icons";const { Sider } = Layout;const items = [getItem("Option 1", "1", <PieChartOutlined />),getItem("Option 2", "2", <DesktopOutlined />),getItem("User", "sub1", <UserOutlined />, [getItem("Tom", "3"),getItem("Bill", "4"),getItem("Alex", "5"),]),getItem("Team", "sub2", <TeamOutlined />, [getItem("Team 1", "6"),getItem("Team 2", "8"),]),getItem("Files", "9", <FileOutlined />),
];function getItem(label, key, icon, children) {return {key,icon,children,label,};
}const CommonAside = () => {const [collapsed, setCollapsed] = useState(false);return (<Sidercollapsiblecollapsed={collapsed}onCollapse={(value) => setCollapsed(value)}><h3 style={{ margin: 16, color: "white" }}>通用后台管理系统</h3><Menutheme="dark"defaultSelectedKeys={["1"]}mode="inline"items={items}/></Sider>);
};export default CommonAside;
import React from "react";
// 引入子路由出口
import { Outlet } from "react-router-dom";
import { Breadcrumb, Layout, theme } from "antd";
import CommonAside from "../components/commonAside";
const { Header, Content, Footer } = Layout;const Main = () => {const {token: { colorBgContainer, borderRadiusLG },} = theme.useToken();return (<Layout style={{ minHeight: "100vh" }}><CommonAside /><Layout><Header style={{ padding: 0, background: colorBgContainer }} /><Content style={{ margin: "0 16px" }}><Breadcrumb style={{ margin: "16px 0" }}><Breadcrumb.Item>User</Breadcrumb.Item><Breadcrumb.Item>Bill</Breadcrumb.Item></Breadcrumb><divstyle={{padding: 24,minHeight: 360,background: colorBgContainer,borderRadius: borderRadiusLG,}}>Bill is a cat.</div></Content><Footer style={{ textAlign: "center" }}>Ant Design ©{new Date().getFullYear()} Created by Ant UED</Footer></Layout></Layout>);
};export default Main;
Aside组件实现
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'}]}]
import React, { useState } from "react";
import { Layout, Menu } from "antd";
import * as Icon from "@ant-design/icons";
import MenuConfig from "../../config/index";const { Sider } = Layout;// 动态获取icon
const iconToElement = (iconName) => React.createElement(Icon[iconName]);// 处理菜单数据  items项设置必须要有key  icon  label
const menuItems = MenuConfig.map((item) => {// 没有子菜单const child = {key: item.path,icon: iconToElement(item.icon),label: item.label,};//  有子菜单if (item.children) {child.children = item.children.map((child) => {return {key: child.path,icon: iconToElement(child.icon),label: child.label,};});}return child;
});const CommonAside = () => {const [collapsed, setCollapsed] = useState(false);return (<Sidercollapsiblecollapsed={collapsed}onCollapse={(value) => setCollapsed(value)}><h3 style={{ margin: 16, color: "white" }}>通用后台管理系统</h3><Menutheme="dark"defaultSelectedKeys={["1"]}mode="inline"items={menuItems}/></Sider>);
};export default CommonAside;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/78460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于AWS Marketplace的快速解决方案:从选型到部署实战

1. 引言&#xff1a;为什么选择AWS Marketplace&#xff1f; 在数字化转型的背景下&#xff0c;企业需要快速获取成熟的软件工具和服务以降低开发成本。AWS Marketplace 作为亚马逊云科技的官方应用商店&#xff0c;提供超过万款预配置的第三方和AWS原生解决方案&#xff0c;涵…

2021年第十二届蓝桥杯省赛B组C++题解

2021年第十二届蓝桥杯省赛B组C题解 关键词&#xff1a;蓝桥杯、省赛、题解、C、算法 一、个人见解 第十二届蓝桥杯省赛B组共有10道题目&#xff0c;包含5道填空题&#xff08;T1-T5&#xff09;和5道编程题&#xff08;T6-T10&#xff09;&#xff0c;总分150分。比赛时长4小…

日语学习-日语知识点小记-进阶-JLPT-N1阶段(1):语法单词

日语学习-日语知识点小记-进阶-JLPT-N1阶段&#xff08;1&#xff09;&#xff1a;语法单词 1、前言&#xff08;1&#xff09;情况说明&#xff08;2&#xff09;工程师的信仰&#xff08;3&#xff09;高级语法N1语法和难点一、N1语法学习内容&#xff08;高级语法&#xff…

Python|Pyppeteer实现自动登录小红书(32)

前言 本文是该专栏的第32篇,结合优质项目案例持续分享Pyppeteer的干货知识,记得关注。 本文中,笔者以小红书为例,基于Pyppeteer实现自动登录“小红书”。 需要注意的是,对Pyppeteer不太熟悉的同学,可往前翻阅本专栏前面介绍的Pyppeteer知识点,本专栏将带你了解并熟练使…

【翻译、转载】【转载】LLM 的函数调用与 MCP

来源&#xff1a; https://www.dailydoseofds.com/p/function-calling-mcp-for-llms/ 【代码以图像显示的是原文内容&#xff0c;以代码形式显示的是大模型给出的参考】 LLM 的函数调用与 MCP 在 MCP 变得像现在这样主流&#xff08;或流行&#xff09;之前&#xff0c;大多…

【QT】QT中http协议和json数据的解析-http获取天气预报

QT中http协议和json数据的解析 1.http协议的原理2.QT中http协议的通信流程2.1 方法步骤 3.使用http协议&#xff08;通过http下载图片和获取天气预报信息&#xff09;3.1 http下载网络上的图片(下载小文件)3.1.1 示例代码3.1.2 现象 3.2 获取网络上天气预报3.2.1 免费的天气预报…

hot100:链表倒数k个节点- 力扣(LeetCode)

题目&#xff1a; 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该链表中倒数第k个节点。 示例一&#xff1a; 输入&#xff1a;{1,2,3,4,5},2 返回值&#xff1a;{4,5} 说明&#xff1a;返回倒数第2个节点4&#xff0c;系统会打印后面所有的节点来比较。 …

Spring AI 实战:第十一章、Spring AI Agent之知行合一

引言:智能体的知行辩证法 “知为行之始,行为知之成”,王阳明的哲学智慧在AI时代焕发光彩。智能体(LLM Agent)的进化之路,正是"认知-决策-执行"这一闭环的完美诠释: 知明理:融合大语言模型的推理能力与知识图谱的结构化认知行致用:基于ReAct模式的动态工具调…

365打卡第R6周: LSTM实现糖尿病探索与预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 &#x1f3e1; 我的环境&#xff1a; 语言环境&#xff1a;Python3.10 编译器&#xff1a;Jupyter Lab 深度学习环境&#xff1a;torch2.5.1 torchvision0…

W-TinyLFU缓存驱逐算法解析

文章目录 1. 背景与概述1.1 什么是缓存驱逐算法1.2 W-TinyLFU 的定义与价值 2. 核心思想与设计理念2.1 时间局部性与频率局部性的结合2.2 高效的频率统计2.3 窗口机制的引入 3. 架构设计与组件3.1 整体架构3.2 窗口缓存&#xff08;Window Cache&#xff09;3.3 主缓存&#xf…

[特殊字符] 人工智能大模型之开源大语言模型汇总(国内外开源项目模型汇总) [特殊字符]

Large Language Model (LLM) 即大规模语言模型&#xff0c;是一种基于深度学习的自然语言处理模型&#xff0c;它能够学习到自然语言的语法和语义&#xff0c;从而可以生成人类可读的文本。 所谓 "语言模型"&#xff0c;就是只用来处理语言文字&#xff08;或者符号…

文章记单词 | 第60篇(六级)

一&#xff0c;单词释义 liar&#xff1a;英 [ˈlaɪə(r)]&#xff1b;美 [ˈlaɪər]&#xff1b;n. 说谎者verbal&#xff1a;英 [ˈvɜːbl]&#xff1b;美 [ˈvɜːrbl]&#xff1b;adj. 言语的&#xff1b;文字的&#xff1b;口头的&#xff1b;动词的comprehension&…

AI日报 · 2025年04月30日|OpenAI 回滚 GPT-4o 更新以解决“谄媚”问题

过去24小时&#xff0c;全球人工智能领域持续快速发展。从模型行为调整到平台工具更新&#xff0c;再到行业安全规范的探讨&#xff0c;以下是为您精选的重点动态&#xff1a; 1、OpenAI 回滚 GPT-4o 更新以解决“谄媚”问题 针对用户反馈最新版 GPT-4o 模型表现出过度“谄媚…

Linux54 源码包的安装、修改环境变量解决 axel命令找不到;getfacl;测试

始终报错 . 补充链接 tinfo 库时报错软件包 ncurses-devel-5.9-14.20130511.el7_4.x86_64 已安装并且是最新版本 没有可用软件包 tinfo-devel。 无须任何处理 make LDLIBS“-lncurses"报错编译时报错make LDLIBS”-lncurses" &#xff1f; /opt/rh/devtoolset-11/roo…

FPGA----基于ZYNQ 7020实现EPICS通信系统

1、本实验过程来自博b站大神《神电测控》&#xff0c;原文地址&#xff1a; EPICS实战(上位机篇)&#xff1a;基于LV ZYNQ实现的EPICS通信系统(大物理) - 哔哩哔哩https://www.bilibili.com/opus/933476043369480224EPICS实战(下位机篇)&#xff1a;基于LV ZYNQ实现的EPICS通信…

实验四 增强型可靠文件传输系统

一、实验目的和任务 掌握基于队列的多文件传输机制理解断点续传的实现原理学习文件传输完整性保障方法 二、实验内容 基础功能验证 单文件传输功能测试服务器状态监控测试传输日志记录验证 新增功能实现 多文件队列传输功能断点续传支持 三、实验步骤 4.1 客户端功能扩…

网络Tips20-003

1.E1载波的控制开销占2/32*100%6.25%&#xff0c;E1载波的基本帧传送时间是125uS。 2.计算机在一个指令周期的过程中&#xff0c;为从内存读取指令操作码&#xff0c;首先要将.程序计数器(PC)的内容送到地址总线上 3.3DES算法:密码学中&#xff0c;3DES是三重数据加密算法通称…

【MySQL】索引(重要)

目录 一、索引本质&#xff1a; 索引的核心作用 索引的优缺点 二、预备知识&#xff1a; 硬件理解&#xff1a; 软件理解&#xff1a; MySQL与磁盘交互基本单位&#xff1a; 三、索引的理解&#xff1a; 理解page&#xff1a; 单个page&#xff1a; 多个page&#x…

【深入浅出MySQL】之数据类型介绍

【深入浅出MySQL】之数据类型介绍 MySQL中常见的数据类型一览为什么需要如此多的数据类型数值类型BIT&#xff08;M&#xff09;类型INT类型TINYINT类型BIGINT类型浮点数类型float类型DECIMAL(M,D)类型区别总结 字符串类型CHAR类型VARCHAR(M)类型 日期和时间类型enum和set类型 …

数字化时代下,软件测试中的渗透测试是如何保障安全的?

在如今数字化与信息化的时代&#xff0c;软件测试中存在渗透测试&#xff0c;其位置十分重要&#xff0c;它借助模拟恶意攻击的方式&#xff0c;去发现软件系统所存在的漏洞以及安全问题&#xff0c;这是保障软件安全的关键环节&#xff0c;接下来我会对它的各个方面进行详细介…