学习React-23-React-router

Router

在 React Router v7 中,官方把原先拆成两个包(react-router + react-router-dom)的代码合并回 react-router 这一个核心包。

因此,新项目只需安装 react-router,不必再装 react-router-dom;后者已标记为 deprecated,仅保留向后兼容 。

安装

bash 复制代码
npm i react-router@latest

牛刀小试

ts 复制代码
// 新建Home页面
import { NavLink } from "react-router"; // 路由跳转
export default function Home() {
  return (
    <div>
      <h1>Home</h1>
      <NavLink to="/about">About</NavLink>
    </div>
  );
}
// 新建About页面
export default function About() {
  return (
    <div>
      <h1>About</h1>
    </div>
  );
}

// 配置router
import Home from "../pages/Home";
import About from "../pages/About";
import { createBrowserRouter } from "react-router";

const router = createBrowserRouter([
  {
    path: "/",
    Component: Home,
  },
  {
    path: "/about",
    Component: About,
  }
])

export default router;

// 引用router(App.tsx)
import { RouterProvider } from 'react-router'
import router from './router'
function App() {

  return (
    <>
      <div className="App">
        <RouterProvider router={router} />
      </div>
    </>
  )
}

export default App

路由模式

模式 URL 存在位置 典型场景 所在包(v7)
1. BrowserRouter 浏览器地址栏 线上 Web 站点 react-router
2. HashRouter location.hash 内网、单文件部署、老浏览器 react-router
3. MemoryRouter 内存数组 测试、React Native、微前端 react-router
4. StaticRouter 字符串路径 服务端渲染(SSR) react-router/dom
createBrowserRouter ------ "正常网址"

地址栏:https://example.com/about
刷新 404 → 需要服务器配回退 /* → index.html

ts 复制代码
import { BrowserRouter } from 'react-router'

import Home from "../pages/Home";
import About from "../pages/About";
import { createBrowserRouter } from "react-router";

const router = createBrowserRouter([
  {
    path: "/",
    Component: Home,
  },
  {
    path: "/about",
    Component: About,
  }
])

export default router;

例如nginx

HashRouter ------ "# 后面自己玩"

地址栏:https://example.com/#/about

刷新不 404,无需服务端配置;SEO 几乎为零。

ts 复制代码
import Home from "../pages/Home";
import About from "../pages/About";
import { createHashRouter } from "react-router";

const router = createHashRouter([
  {
    path: "/",
    Component: Home,
  },
  {
    path: "/about",
    Component: About,
  }
])

export default router;
MemoryRouter ------ "地址栏看不见"

适用于:单元测试(@testing-library/react)、React Native 导航嵌套、微前端子应用隐藏路由

ts 复制代码
import Home from "../pages/Home";
import About from "../pages/About";
import { createHashRouter } from "react-router";

const router = createMemoryRouter ([
  {
    path: "/",
    Component: Home,
  },
  {
    path: "/about",
    Component: About,
  }
])

export default router;
StaticRouter ------ "服务端字符串"

客户端首屏直出,不维护历史栈;location 是只读字符串。

ts 复制代码
// server.js (Node)
import { StaticRouter } from 'react-router/dom/server'

const html = ReactDOMServer.renderToString(
  <StaticRouter location={req.path}>  {/* 把 Node 收到的路径直接传进来 */}
    <App />
  </StaticRouter>
)

路由种类

嵌套路由
复制代码
嵌套路由是指在父级路由下定义子路由,形成层级结构。适用于具有多层布局的应用程序,例如管理后台的侧边栏导航或带有
标签页的内容区域。
ts 复制代码
import Home from "../pages/Home";
import About from "../pages/About";
import { createBrowserRouter } from "react-router";
import Layout from "../pages/Layout";

const router = createBrowserRouter([
  {
    path: "/index",
    Component: Layout,
    // 子路由
    children: [
      {
        path: "about",
        Component: About,
      },
      {
        path: "home",
        Component: Home,
      },
    ]
  },

])

export default router;
ts 复制代码
import React from 'react';
import { Outlet } from 'react-router';


const Content: React.FC = () => (
	// 父组件中需添加<Outlet />作为子路由的占位符。
  <Outlet />
);

export default Content;

注:子路由的请求路径http://localhost:5173/index/home
最佳实践

  • 保持嵌套层级不超过3层以避免复杂度。
  • 使用命名路由简化长路径的跳转。
  • 结合懒加载优化性能:
ts 复制代码
// React Router懒加载
{ path: 'home', element: React.lazy(() => import('./Home.jsx')) }
布局路由
复制代码
路由布局是指在Web应用中,通过定义不同的路由路径来组织和管理页面或视图的显示方式。前端框架如React、Vue、Angular等通常
提供路由功能,允许开发者根据URL的变化动态加载不同的组件或页面。
ts 复制代码
const router = createBrowserRouter([
    { 
        // path: '/index', //省略 
        Component: Layout,
        children: [
            {
                path: 'home',
                Component: Home,
            },
            {
                path: 'about',
                Component: About,
            },
        ]
    },
]);
索引路由
复制代码
 索引路由是一种通过建立索引来优化路由查找效率的技术,常用于网络通信、数据库查询或前端框架(如React Router)中。其核心
 思想是将路由路径映射到快速可检索的数据结构(如哈希表、字典或树),减少线性搜索的时间复杂度。
 索引路由 = 父路径尾部的默认子页,它没有 path,用 index: true 声明。下面把刚才的嵌套路由改成「索引路由」版本:访问
  /index 时直接渲染 Home,不再额外拼路径。
ts 复制代码
import { createBrowserRouter } from 'react-router-dom';
import Layout from './pages/Layout';
import Home from './pages/Home';
import About from './pages/About';

const router = createBrowserRouter([
  {
    path: '/index',
    Component: Layout,
    children: [
      { index: true,          Component: Home  }, // ← 索引路由
      { path: 'about',        Component: About },
    ],
  },
]);

export default router;
前缀路由
复制代码
前缀路由(又叫通配路由)用来「把剩余路径全部收归当前路由处理」,写法就是在 path 末尾加 /*。

例如: 访问 /files/任意/任意/任意...... 都会落到 Files 组件,由它自己再决定到底展示什么。

ts 复制代码
import { createBrowserRouter } from 'react-router-dom';
import Layout from './pages/Layout';
import Files from './pages/Files';   // 自己建的组件

const router = createBrowserRouter([
  {
    path: '/files',
    Component: Layout,
    children: [
      {
        path: '*',          // ← 前缀路由(通配)
        Component: Files,
      },
    ],
  },
]);

export default router;

Files.tsx 里可以继续用 useParams() 拿到「剩余段」:

ts 复制代码
import { useParams } from 'react-router';

export default function Files() {
  const params = useParams();   // params['*'] 就是剩余路径
  return <h2>当前浏览路径:/files/{params['*']}</h2>;
}

访问验证

/files → Layout + Files(params[''] 为空)

/files/a/b/c → Layout + Files(params[''] = 'a/b/c')

动态路由
复制代码
动态路由:路径里带「:参数名」占位符,匹配任意字符串,参数值通过 useParams() 读取。
ts 复制代码
const router = createBrowserRouter([
    {
        path: '/',
        Component: Layout,
        children: [
            {
                path: 'home/:id', 
                Component: Home,
            },
            {
                path: 'about',
                Component: About,
            },
        ]
    },
]);


//在组件中获取参数
import { useParams } from "react-router";

function Card() {
  let params = useParams();
  console.log(params.id);
}

访问路径:http://localhost:3000/home/123

路由小DEMO

使用的组件库Ant Desgin

Content组件

ts 复制代码
import React from 'react';
import { Outlet } from 'react-router';


const Content: React.FC = () => (
  <Outlet />
);

export default Content;

Header组件

ts 复制代码
import { Breadcrumb } from 'antd';
export function Headers() {
  return (
    <div>
      <Breadcrumb
      items={[
        {
          title: 'Home',
        },
        {
          title: 'List',
        },
        {
          title: 'APP',
        },
        {
          title: 'An Application',
        },
      ]}
    />
    </div>
  )
}

export default Headers

Menu组件

ts 复制代码
import { AppstoreOutlined, MailOutlined } from '@ant-design/icons';
import type { MenuProps } from 'antd';
import { Menu as AntdMenu } from 'antd';
import { useNavigate } from 'react-router';



const Menu: React.FC = () => {
  // Required 将变量设置为必填
  type MenuItem = Required<MenuProps>['items'][number];

  const items: MenuItem[] = [
    {
      key: '/home',
      icon: <MailOutlined />,
      label: 'Home',
    },
    {
      key: '/about',
      icon: <AppstoreOutlined />,
      label: 'About',

    }
  ];

  const navigate = useNavigate();
  const onClick: MenuProps['onClick'] = (e) => {
    console.log('click', e);
    navigate(e.key)


  };
  return < AntdMenu onClick={onClick} style={{ height: '100vh' }} mode="vertical" items={items} />
}


export default Menu;

Layout组件

ts 复制代码
import React from 'react';
import {  Layout as AntdLayout } from 'antd';
import Headers from './Header';
import Menu from './Menu';
import Content from './Content';



const Layout: React.FC = () => (
  <AntdLayout >
    <AntdLayout.Sider >
      <Menu />
    </AntdLayout.Sider>
    <AntdLayout>
      <Headers></Headers>
      <Content></Content>
    </AntdLayout>
  </AntdLayout>
);

export default Layout;

目录结构

相关推荐
i***27951 小时前
【golang学习之旅】使用VScode安装配置Go开发环境
vscode·学习·golang
hd51cc1 小时前
文档与视图 学习笔记
笔记·学习
我叫张小白。1 小时前
TypeScript对象类型与接口:构建复杂数据结构
前端·javascript·typescript
墨客希2 小时前
如何快速掌握大型Vue项目
前端·javascript·vue.js
大福ya2 小时前
AI开源项目改造NextChat(ChatGPT-Next-Web)实现前端SSR改造打造一个初始框架
前端·chatgpt·前端框架·开源·aigc·reactjs·ai编程
n***33352 小时前
SpringBoot返回文件让前端下载的几种方式
前端·spring boot·后端
纯粹的热爱2 小时前
🌐 阿里云 Linux 服务器 Let's Encrypt 免费 SSL 证书完整部署指南
前端
北辰alk2 小时前
Vue3 自定义指令深度解析:从基础到高级应用的完整指南
前端·vue.js
小熊哥7222 小时前
谈谈最进学习(低延迟)直播项目的坎坷与收获
前端