集中式路由

Tutorial: ReactTS案例 Category: React Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
  1. 创建路由 src\router\index.tsx
import { Spin } from "antd";
import { lazy, ReactNode, Suspense } from "react";
import { Navigate, NonIndexRouteObject, RouteObject } from "react-router-dom";
import {
  UserOutlined,
  LaptopOutlined,
  DashboardOutlined,
  GoldOutlined,
  LockOutlined,
} from "@ant-design/icons";

import Login from "../pages/login";
import AppLayout from "../components/AppLayout";
import DashBoard from "../pages/dashBoard";

const User = lazy(() => import("../pages/user"));
const Admin = lazy(() => import("../pages/admin"));
const Role = lazy(() => import("../pages/role"));

export interface IRouter extends NonIndexRouteObject {
  path: string;
  label?: string;
  hide?: boolean;
  icon?: ReactNode;
  children?: IRouter[];
}

const lazyLoad = (children: ReactNode) => {
  return <Suspense fallback={<Spin />}>{children}</Suspense>;
};

const router: IRouter[] = [
  {
    path: "/",
    label: "首页",
    icon: <LaptopOutlined />,
    element: <Navigate to="/dashboard" replace={true} />,
    hide: true,
  },
  {
    path: "/dashboard",
    label: "仪表盘",
    icon: <DashboardOutlined />,
    // 没有路由管理的页面, 可以这么操作
    // const AppLayout = ({ children }: { children?: ReactNode })
    // {children}
    // <Outlet />
    element: <AppLayout> {lazyLoad(<DashBoard />)}</AppLayout>,
  },
  {
    path: "/user",
    label: "用户管理",
    icon: <UserOutlined />,
    element: <AppLayout />,
    children: [
      {
        path: "/user/list",
        label: "用户列表",
        icon: <UserOutlined />,
        element: lazyLoad(<User />),
      },
    ],
  },
  {
    path: "/admin",
    label: "管理员管理",
    icon: <LockOutlined />,
    element: <AppLayout />,
    children: [
      {
        path: "/admin/list",
        label: "管理员列表",
        icon: <UserOutlined />,
        element: lazyLoad(<Admin />),
      },
    ],
  },
  {
    path: "/role",
    label: "角色管理",
    icon: <GoldOutlined />,
    element: <AppLayout />,
    children: [
      {
        path: "/role/list",
        label: "角色列表",
        icon: <UserOutlined />,
        element: lazyLoad(<Role />),
      },
    ],
  },
  {
    path: "/login",
    element: <Login />,
  },
];

export default router;
  1. 创建布局管理页面 src\components\AppLayout\index.tsx
import React, { ReactNode, useEffect, useState } from "react";
import { Breadcrumb, Layout, Menu, theme } from "antd";
import { Outlet, useNavigate } from "react-router-dom";
import { ItemType } from "antd/es/menu/hooks/useItems";
import { MenuInfo } from "rc-menu/lib/interface";

import router, { IRouter } from "../../router";

const { Header, Content, Sider } = Layout;
const navBar: ItemType[] = [
  {
    key: "1",
    label: "首页",
  },
  {
    key: "2",
    label: "代码",
  },
  {
    key: "3",
    label: "关于",
  },
];

const AppLayout = ({ children }: { children?: ReactNode }) => {
  const {
    token: { colorBgContainer },
  } = theme.useToken();
  const navigateTo = useNavigate();

  // 解析路由强转
  const getMenuList = (routers: IRouter[]): ItemType[] => {
    let t: ItemType[] = [];
    for (let r of routers) {
      let tmp = {
        key: r.path,
        label: r.label,
        icon: r.icon,
      } as ItemType;
      if (r.children) {
        // @ts-ignore
        tmp.children = getMenuList(r.children);
      }
      t.push(tmp);
    }
    return t;
  };

  // 跳转到页面
  const goTo = (info: MenuInfo) => {
    navigateTo(info.key);
  };

  return (
    <Layout>
      <Header className="header">
        <div className="logo" />
        <Menu
          theme="dark"
          mode="horizontal"
          defaultSelectedKeys={["2"]}
          items={navBar}
        />
      </Header>
      <Layout>
        <Sider width={200} style={{ background: colorBgContainer }}>
          <Menu
            mode="inline"
            defaultSelectedKeys={["1"]}
            defaultOpenKeys={["sub1"]}
            style={{ height: "100%", borderRight: 0 }}
            items={getMenuList(router)}
            onClick={goTo}
          />
        </Sider>
        <Layout style={{ padding: "0 24px 24px" }}>
          <Breadcrumb style={{ margin: "16px 0" }}>
            <Breadcrumb.Item>Home</Breadcrumb.Item>
            <Breadcrumb.Item>List</Breadcrumb.Item>
            <Breadcrumb.Item>App</Breadcrumb.Item>
          </Breadcrumb>
          <Content
            style={{
              padding: 24,
              margin: 0,
              minHeight: 280,
              background: colorBgContainer,
            }}
          >
            {children}
            <Outlet />
          </Content>
        </Layout>
      </Layout>
    </Layout>
  );
};

export default AppLayout;
  1. 需要新增的页面
$ ls -R src/pages/
src/pages/:
admin/  dashBoard/  login/  role/  user/

src/pages/admin:
index.tsx

src/pages/dashBoard:
index.tsx

src/pages/login:
index.tsx  login.d.ts  login.module.scss

src/pages/role:
index.tsx

src/pages/user:
components/  index.tsx  user.d.ts  user.module.scss

src/pages/user/components:
AddUser.tsx  DeleteUser.tsx  EditUser.tsx
  1. App.tsx 引入路由
import React, { Suspense } from "react";
import { Spin } from "antd";
import { useRoutes } from "react-router-dom";
import router from "./router";

function App() {
  return (
    <>
      <Suspense fallback={<Spin />}>{useRoutes(router)}</Suspense>
    </>
  );
}

export default App;
Prev: 新建公共布局 Next: None