当前位置: 首页 > news >正文

React Router v6 核心组件

下面,我们来系统的梳理关于 React Router v6 核心组件 的基本知识点:


一、BrowserRouter - 路由容器组件

1.1 核心功能与作用

<BrowserRouter> 是 React Router 的基础容器组件,提供基于 HTML5 History API 的路由功能:

  • 启用客户端路由:实现无刷新页面导航
  • 管理浏览历史:支持前进/后退操作
  • 提供路由上下文:为子组件提供路由信息
  • 同步URL与UI:URL变化时自动更新组件树

1.2 使用方式

// 入口文件 index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode><BrowserRouter><App /></BrowserRouter></React.StrictMode>
);

1.3 关键配置项

<BrowserRouterbasename="/app" // 基础路径(适用于子目录部署)window={window} // 自定义window对象(SSR时使用)
>{/* 应用内容 */}
</BrowserRouter>

1.4 实现原理

使用
创建
监听
触发
通知
BrowserRouter
history库
history对象
popstate事件
路由更新
Route组件

二、Routes - 路由配置中心

2.1 核心功能与作用

<Routes> 是 v6 版本引入的核心组件,取代了 v5 中的 <Switch>

  • 智能路由匹配:自动选择最佳匹配的路由
  • 嵌套路由支持:简化路由层级结构
  • 相对路径处理:自动继承父路由路径
  • 路由优先级管理:不再依赖顺序(但仍建议合理排序)

2.2 基本使用

import { Routes, Route } from 'react-router-dom';function App() {return (<Routes><Route path="/" element={<HomePage />} /><Route path="about" element={<AboutPage />} /><Route path="products" element={<ProductsPage />} /></Routes>);
}

2.3 嵌套路由模式

<Routes><Route path="/" element={<Layout />}>{/* 嵌套路由自动继承父路径 */}<Route index element={<Home />} /><Route path="dashboard" element={<Dashboard />} /><Route path="settings" element={<Settings />} /></Route>
</Routes>// Layout组件中定义出口
function Layout() {return (<div><Header /><main><Outlet /> {/* 子路由在此渲染 */}</main><Footer /></div>);
}

2.4 路由匹配规则

模式匹配路径说明
/根路径精确匹配
about/about相对路径
users/:id/users/123路径参数
posts/*/posts/2023/react通配符匹配
docs/:section?/docs 或 /docs/getting-started可选参数

三、Route - 路由配置单元

3.1 核心属性解析

属性类型说明必需
pathstring路由匹配路径否(index路由不需要)
elementReactNode匹配时渲染的组件
indexboolean标记为索引路由
caseSensitiveboolean是否区分大小写

3.2 索引路由(Index Routes)

<Route path="/teams" element={<Teams />}>{/* 当URL为/teams时渲染TeamList */}<Route index element={<TeamList />} /><Route path=":teamId" element={<TeamDetail />} />
</Route>

3.3 动态路由参数

<Route path="users/:userId" element={<UserProfile />} />// 在UserProfile组件中获取参数
import { useParams } from 'react-router-dom';function UserProfile() {const { userId } = useParams();return <div>用户ID: {userId}</div>;
}

3.4 布局路由模式

<Routes>{/* 公共布局 */}<Route element={<MainLayout />}><Route path="/" element={<Home />} /><Route path="about" element={<About />} /></Route>{/* 独立布局 */}<Route element={<AuthLayout />}><Route path="login" element={<Login />} /><Route path="register" element={<Register />} /></Route>
</Routes>

四、路由导航与编程控制

4.1 声明式导航(Link组件)

import { Link } from 'react-router-dom';function Navigation() {return (<nav><Link to="/">首页</Link><Link to="/about">关于</Link><Link to="/users/123">用户资料</Link>{/* 高级用法 */}<Link to="/dashboard"state={{ from: location.pathname }} // 传递状态replace={true} // 替换历史记录reloadDocument={false} // 是否整页刷新>控制面板</Link></nav>);
}

4.2 编程式导航(useNavigate)

import { useNavigate } from 'react-router-dom';function LoginForm() {const navigate = useNavigate();const handleSubmit = async (e) => {e.preventDefault();try {await login(credentials);// 导航到目标页面navigate('/dashboard');// 相对路径导航navigate('../success');// 带状态导航navigate('/profile', { state: { newUser: true } });// 替换历史记录navigate('/home', { replace: true });// 前进/后退navigate(-1); // 后退一页navigate(2);  // 前进两页} catch (error) {console.error('登录失败', error);}};return (<form onSubmit={handleSubmit}>{/* 表单内容 */}</form>);
}

4.3 获取路由信息

import { useLocation, useSearchParams,useRouteMatch 
} from 'react-router-dom';function ProductPage() {const location = useLocation();const [searchParams, setSearchParams] = useSearchParams();// 获取查询参数const category = searchParams.get('category');const sort = searchParams.get('sort');// 获取路径匹配信息(v6中较少使用)const match = useRouteMatch();// 更新查询参数const updateSort = (newSort) => {setSearchParams({ ...Object.fromEntries(searchParams), sort: newSort });};return (<div><h2>产品列表</h2><p>当前分类: {category}</p><button onClick={() => updateSort('price')}>按价格排序</button>{/* 显示完整路径信息 */}<pre>{JSON.stringify(location, null, 2)}</pre></div>);
}

五、高级路由模式

5.1 路由守卫(鉴权)

// src/components/AuthRoute.jsx
import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';function AuthRoute({ children, roles = [] }) {const { user, isAuthenticated } = useAuth();const location = useLocation();if (!isAuthenticated) {// 未登录重定向到登录页,并保存来源位置return <Navigate to="/login" state={{ from: location }} replace />;}if (roles.length > 0 && !roles.some(role => user.roles.includes(role))) {// 无权限访问return <Navigate to="/unauthorized" replace />;}return children;
}// 使用
<Routepath="/admin"element={<AuthRoute roles={['admin']}><AdminDashboard /></AuthRoute>}
/>

5.2 路由懒加载

import { lazy, Suspense } from 'react';const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Contact = lazy(() => import('./pages/Contact'));function App() {return (<Suspense fallback={<div>加载中...</div>}><Routes><Route path="/" element={<Home />} /><Route path="about" element={<About />} /><Route path="contact" element={<Contact />} /></Routes></Suspense>);
}

5.3 错误边界处理

<Route path="/dashboard"element={<Dashboard />}errorElement={<ErrorBoundary />} // 组件级错误边界
><Route path="analytics"element={<Analytics />}errorElement={<AnalyticsError />} // 嵌套错误边界/>
</Route>

六、实践与项目结构

6.1 推荐项目结构

src/
├── components/
│   ├── layout/
│   │   ├── MainLayout.jsx
│   │   └── AuthLayout.jsx
│   └── ui/
│       ├── Header.jsx
│       └── Footer.jsx
├── pages/
│   ├── Home.jsx
│   ├── About.jsx
│   ├── Dashboard.jsx
│   └── ...
├── routes/
│   ├── index.js        # 主路由配置
│   ├── publicRoutes.js # 公开路由
│   └── privateRoutes.js # 需要认证的路由
├── App.js
└── index.js

6.2 集中式路由配置

// src/routes/index.js
import { lazy } from 'react';
import AuthLayout from '../components/layout/AuthLayout';
import MainLayout from '../components/layout/MainLayout';
import AuthRoute from '../components/AuthRoute';const Home = lazy(() => import('../pages/Home'));
const Dashboard = lazy(() => import('../pages/Dashboard'));
const Login = lazy(() => import('../pages/Login'));const routes = [{path: '/',element: <MainLayout />,children: [{ index: true, element: <Home /> },{ path: 'dashboard',element: <AuthRoute><Dashboard /></AuthRoute>},// ...其他受保护路由]},{element: <AuthLayout />,children: [{ path: 'login', element: <Login /> },{ path: 'register', element: <Register /> },{ path: 'forgot-password', element: <ForgotPassword /> },]},{path: '*',element: <NotFoundPage />}
];export default routes;// src/App.js
import { useRoutes } from 'react-router-dom';
import routes from './routes';function App() {return useRoutes(routes);
}export default App;

七、常见问题与解决方案

7.1 路由匹配问题

问题:路由不匹配或匹配错误
解决

// 确保使用正确的路径格式
<Route path="users/:id" /> // 匹配 /users/123// 使用通配符处理未匹配路由
<Route path="*" element={<NotFound />} />// 检查嵌套路由的Outlet位置

7.2 导航循环问题

问题:鉴权逻辑导致无限重定向
解决

// 在AuthRoute组件中添加重定向状态检查
if (location.pathname === '/login') {return children;
}

7.3 滚动恢复问题

问题:页面切换后滚动位置不正确
解决

// 创建自定义滚动恢复组件
function ScrollToTop() {const { pathname } = useLocation();useEffect(() => {window.scrollTo(0, 0);}, [pathname]);return null;
}// 在路由配置中使用
<Routes><Route element={<><ScrollToTop /><MainLayout /></>}>{/* ...路由配置 */}</Route>
</Routes>

7.4 查询参数处理

问题:获取和更新查询参数
解决

const [searchParams, setSearchParams] = useSearchParams();// 获取参数
const page = searchParams.get('page');// 更新参数
const updatePage = (newPage) => {searchParams.set('page', newPage);setSearchParams(searchParams);
};// 保留现有参数添加新参数
setSearchParams({ ...Object.fromEntries(searchParams), sort: 'asc' });

八、总结

8.1 React Router v6 核心概念

组件功能关键特性
BrowserRouter路由容器提供路由上下文、历史管理
Routes路由配置中心智能匹配、嵌套路由支持
Route路由单元路径映射、动态参数、布局控制

8.2 实践总结

  1. 合理组织路由:采用集中式配置管理路由
  2. 嵌套路由优化:使用布局组件和Outlet实现UI复用
  3. 路由守卫实现:通过高阶组件保护敏感路由
  4. 懒加载提升性能:结合Suspense实现代码分割
  5. 错误边界处理:提供友好的错误恢复体验

8.3 核心API速查

API功能使用场景
useNavigate编程导航表单提交后跳转
useParams获取路径参数动态路由数据加载
useLocation获取位置信息页面跟踪、路由守卫
useSearchParams操作查询参数筛选、排序功能
Outlet渲染嵌套路由布局组件中
http://www.dtcms.com/a/303479.html

相关文章:

  • 关闭 UniGetUI 自动 Pip 更新,有效避免 Anaconda 环境冲突教程
  • 基于Vue3.0+Express的前后端分离的任务清单管理系统
  • Leaflet 综合案例-矢量图层控制
  • 二分查找的「左右为难」:如何优雅地找到数组中元素的首尾位置
  • SQL笔试面试
  • 深入理解 Qt 信号与槽机制的底层逻辑
  • AUTOSAR Mcal SPI - EB工具配置介绍
  • Android Handler 完全指南
  • 手游遇攻击为何要用游戏盾SDK?
  • Linux学习--C语言(指针3)
  • 第三阶段—8天Python从入门到精通【itheima】-139节(pysqark实战-前言介绍)
  • linux du、df命令使用教程
  • AWS Bedrock Claude 3 API的完整指南
  • 基于STM32设计的智慧果园云监测系统_256
  • 从像素到频率:OpenCV傅里叶变换
  • 扑克洗牌
  • NVMe高速传输之摆脱XDMA设计18:PRP控制模块设计
  • NVMe高速传输之摆脱XDMA设计21:PCIe请求模块设计(下)
  • 机器学习基础-matplotlib
  • clock_nanosleep系统调用及示例
  • node后端-JWT认证
  • Excel VBA宏的使用
  • 大模型应用班-第3课 从Excel到大屏:AI编程实战全解析 HW3 从零到一:香港疫情数据看板开发实战指南
  • 【GoLang #4】:Go 语言 函数详述(定义调用 | 匿名函数 闭包 | defer)
  • windows clion远程连接ubuntu运行调试nginx-1.22.1版本
  • 【优先级高,先补充】基于文本增强跨模态特征交互注意网络的多模态情感分析
  • SVN与GIT的区别,分别使用与哪些管理场景?
  • 《汇编语言:基于X86处理器》第10章 结构和宏(2)
  • Linux——线程池的模拟实现
  • 解决c++静态成员编译报错:‘xxx‘ is not a member of ‘xxx‘ 问题