• react 项目路由配置(react-router-dom 版本 v6.3、v6.4)


    根据 react-router-dom 的版本,有不同的方式

    一、react-router-dom v6.3

    用到的主要 api:

    • BrowserRouter
    • useRoutes
    • Outlet

    下面是详细步骤:

    1、index.js

    • BrowserRouter 用来实现 单页的客户端路由
    • 使用 BrowserRouter 包裹 App
    • 放在 顶级 位置,重要!!
    • 支持嵌套路由,用于 history 模式
    • hash 模式使用 HashRouter
    import React from "react";
    import ReactDOM from "react-dom/client";
    import "./index.css";
    import App from "./App";
    import reportWebVitals from "./reportWebVitals";
    import { BrowserRouter } from "react-router-dom";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      <BrowserRouter>
        <React.StrictMode>
          <App />
        </React.StrictMode>
      </BrowserRouter>
    );
    
    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    如果遇到下图这种报错,就是没有将 BrowserRouter 像上图一样放在 顶级,一定要放顶级!

    在这里插入图片描述

    2、routes.js

    用 数组 描述路由,包含必要参数 pathelementchildren

    例如:

    import { UserOutlined } from "@ant-design/icons";
    import Abroad from "./pages/Abroad";
    import Domestic from "./pages/Domestic";
    import Layout from "./layout/index";
    import { Navigate } from "react-router-dom";
    
    const routes = [
      {
        title: "平台管理",
        path: "/manage",
        element: <Layout />,
        icon: <UserOutlined />,
        children: [
          {
            title: "境内平台管理",
            path: "/manage/domestic",
            element: <Domestic />,
            icon: <UserOutlined />,
          },
          {
            title: "境外平台管理",
            path: "/manage/abroad",
            element: <Abroad />,
            icon: <UserOutlined />,
          },
        ],
      },
      {
        path: "/",
        element: <Navigate to="/manage/domestic" />,
      },
    ];
    
    export default routes;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    3、App.js

    使用 useRoutes 渲染出一级路由,参数即为我们在上一步的路由数组

    • useRoutes 是 react-router-dom 库中提供的一个 Hook,用于 基于路由配置生成路由匹配器(Router Matcher)的方法
    • useRoutes 接收的路由配置对象应该是一个由 若干个路由配置组成的数组,每个路由配置包含以下属性:
      • path:字符串类型,表示 URL 路径匹配规则;
      • element:React 组件,表示如果 URL 匹配成功后要显示的组件;
      • children:嵌套子路由的路由配置数组。
    import React from "react";
    import { useRoutes } from "react-router-dom";
    import routes from "./routes";
    
    const App = () => {
      const element = useRoutes(routes);
      return <>{element}</>;
    };
    
    export default App;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、layout.jsx

    实际场景,如后台管理项目,需要展示多级路由,我们一般会创建一个layout文件

    • 按照 左 Menu右 Content 的设定来举例
    • 嵌套的二级路由,使用 outlet 渲染(类似于vue中的
    • 例子中,包含了一些菜单处理的代码,如递归渲染、默认选中,可选择性观看
    import React, { useState } from "react";
    import { MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
    import { Layout, Menu, Button, theme } from "antd";
    import { Outlet, useNavigate, useLocation } from "react-router-dom";
    import routes from "../routes/index";
    
    const { Header, Sider, Content } = Layout;
    
    // Menu格式处理
    function getMenu(rout) {
      const rs = rout.map((item) => {
        return {
          label: item.title,
          key: item.path,
          icon: item.icon,
          children: item.children && getMenu(item.children),
        };
      });
      return rs;
    }
    
    // 递归层级
    function findParents(key, tree) {
      let parents = [];
      function findParent(nodes, key) {
        for (let node of nodes) {
          if (node.path === key) {
            return true;
          }
          if (node.children && findParent(node.children, key)) {
            parents.push(node.path);
            return true;
          }
        }
        return false;
      }
      findParent(tree, key);
      parents.push(key);
      return parents;
    }
    
    // 获取当前路由所在层级
    function getOpenKeys(pathname, list) {
      if (!pathname) return ["/manage", "/manage/domestic"];
      let keys = findParents(pathname, list);
      return keys;
    }
    
    const App = () => {
      const [collapsed, setCollapsed] = useState(false);
      const {
        token: { colorBgContainer, borderRadiusLG },
      } = theme.useToken();
    
      // 递归获取有效菜单项
      const list = routes.filter((item) => item.title);
      const items = getMenu(list);
    
      // 菜单,默认展开、选中处理
      const location = useLocation();
      const keys = getOpenKeys(location.pathname, list);
      const defaultSelectedKeys = keys;
      const defaultOpenKeys = keys;
    
      // 跳转
      let navigate = useNavigate();
      function handleClick(e) {
        navigate(e.key);
      }
    
      return (
        <Layout>
          <Sider trigger={null} collapsible collapsed={collapsed}>
            <div style={{ width: "100%", height: "80px" }}></div>
            {/* 菜单 */}
            <Menu
              mode="inline"
              theme="dark"
              defaultSelectedKeys={defaultSelectedKeys}
              defaultOpenKeys={defaultOpenKeys}
              onClick={handleClick}
              items={items}
            ></Menu>
          </Sider>
          <Layout>
            <Header
              style={{
                padding: 0,
                background: colorBgContainer,
              }}
            >
              <Button
                type="text"
                onClick={() => setCollapsed(!collapsed)}
                style={{ marginBottom: 16 }}
              >
                {collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
              </Button>
            </Header>
            <Content
              style={{
                margin: "24px 16px",
                padding: 24,
                minHeight: 280,
                background: colorBgContainer,
                borderRadius: borderRadiusLG,
                overflowY: "auto",
              }}
            >
              {/* 二级路由 */}
              <Outlet />
              
            </Content>
          </Layout>
        </Layout>
      );
    };
    export default App;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    v6.3 的版本,路由设置到此结束,接下来是 v6.4

    二、react-router-dom v6.4

    主要 api:

    • createBrowserRouter
    • RouterProvider
    • Outlet

    在 v6.3 方案的基础上,换掉 index.js 和 App.js 即可

    1、index.js

    BrowserRouter 的使用去掉

    
    import React from "react";
    import ReactDOM from "react-dom/client";
    import "./index.css";
    import App from "./App";
    import reportWebVitals from "./reportWebVitals";
    
    // v6.3 使用此API,v6.4使用会报错
    // import { BrowserRouter } from "react-router-dom";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      // 
      <React.StrictMode>
        <App />
      </React.StrictMode>
      // 
    );
    
    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2、App.js

    useRoutes 的使用去掉,增加 createBrowserRouterRouterProvider 的相关设置

    • createBrowserRouter 创建路由
    • 挂载到 RouterProviderrouter
    
    import React from "react";
    import routes from "./routes";
    
    // v6.3 userRoutes钩子
    // import { useRoutes } from "react-router-dom";
    // const App = () => {
    //   const element = useRoutes(routes);
    //   return <>{element};
    // };
    
    // v6.4 createBrowserRouter + RouterProvider
    import { createBrowserRouter, RouterProvider } from "react-router-dom";
    const router = createBrowserRouter(routes);
    const App = () => {
      return (
        <>
          <RouterProvider router={router} />
        </>
      );
    };
    
    export default App;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    然后就完成啦~

  • 相关阅读:
    使用react-sizeme解决react-grid-layout中侧栏(抽屉)展开或隐藏时不会自适应容器大小的问题
    Github上标星98K!火爆全网的性能调优实战手册,出自腾讯T4大佬
    硬核!国内首款增加多类适应症的人工智能辅助诊断软件完成临床试验
    【从零开始学习 SystemVerilog】2.12、SystemVerilog 数据类型—— Queue(队列)
    【PHP】自研框架QPHP,qphp框架使用
    CUDA编程入门系列(十一)CUDA程序优化技巧
    GIt的使用
    《下一代互联网(IPv6)搭建与运维》
    8、MFC界面开发
    2.1.6.16 漏洞利用-rlogin最高权限登陆
  • 原文地址:https://blog.csdn.net/weixin_42289080/article/details/137882154