react + antd 实现后台管理系统

文章目录


项目效果图

项目完整代码地址

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

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

react-router 安装依赖

配置路由

history模式 /

react 复制代码
// 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模式 #

react 复制代码
// 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路由文件

js 复制代码
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

js 复制代码
import React from 'react'
// 引入子路由出口
import {Outlet} from 'react-router-dom'

const Main = () => {
    return (
        <div>
            <h1>main</h1>
            <Outlet/>
        </div>
    )
}

export default Main

创建子路由home组件

js 复制代码
import React from "react";

import './home.css'
const Home = () => {
  return (
    <div>
      <h1>Home</h1>
    </div>
  );
}

export default Home;

App.js挂载路由router RouterProvider

js 复制代码
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;

导入完整路由组件

js 复制代码
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);

改为懒加载

js 复制代码
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

完整路由搭建

代码

js 复制代码
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
shell 复制代码
npm install antd

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

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" }}>
      <Sider
        collapsible
        collapsed={collapsed}
        onCollapse={(value) => setCollapsed(value)}
      >
        <div className="demo-logo-vertical" />
        <Menu
          theme="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>
          <div
            style={{
              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组件抽取出来

js 复制代码
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 (
    <Sider
      collapsible
      collapsed={collapsed}
      onCollapse={(value) => setCollapsed(value)}
    >
      <h3 style={{ margin: 16, color: "white" }}>通用后台管理系统</h3>
      <Menu
        theme="dark"
        defaultSelectedKeys={["1"]}
        mode="inline"
        items={items}
      />
    </Sider>
  );
};

export default CommonAside;
js 复制代码
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>
          <div
            style={{
              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组件实现
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'
        }
      ]
    }
  ]
js 复制代码
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 (
    <Sider
      collapsible
      collapsed={collapsed}
      onCollapse={(value) => setCollapsed(value)}
    >
      <h3 style={{ margin: 16, color: "white" }}>通用后台管理系统</h3>
      <Menu
        theme="dark"
        defaultSelectedKeys={["1"]}
        mode="inline"
        items={menuItems}
      />
    </Sider>
  );
};

export default CommonAside;
相关推荐
愛芳芳12 分钟前
springboot+mysql+element-plus+vue完整实现汽车租赁系统
前端·vue.js·spring boot·后端·mysql·elementui·汽车
m0_zj1 小时前
55.[前端开发-前端工程化]Day02-包管理工具npm等
前端·npm·node.js
xcLeigh3 小时前
HTML5好看的水果蔬菜在线商城网站源码系列模板9
java·前端·html5·网页源码
星仔_X4 小时前
硬件加速模式Chrome(Edge)闪屏
前端·chrome·edge
2501_915373884 小时前
使用 Vue + Axios 构建与后端交互的高效接口调用方案
前端·vue.js·交互
七灵微8 小时前
ES6入门---第三单元 模块三:async、await
前端·javascript·es6
七灵微10 小时前
ES6入门---第二单元 模块五:模块化
前端·ecmascript·es6
m0_6161884911 小时前
vue3 - keepAlive缓存组件
前端·vue.js·缓存
lh_125412 小时前
Uni-app 组件使用
前端·javascript·uni-app