React 文档
导读与全书目录表:见同目录 01-React 入门:简介·特性与设计范式.md 开头。
react 路由
路由核心概念
js
<Router>:路由的根组件,通常使用 BrowserRouter
<Routes>:路由容器,内部包含多个 <Route>
<Route>:定义路由规则,path 是路径,element 是要渲染的组件
<Link>:导航链接,类似 <a> 标签但不会刷新页面
<Outlet>:用于嵌套路由,显示子路由的内容路由示例
- 基础路由定义
js
// 导入必要的组件
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
function App() {
return (
<Router>
{/* 路由匹配规则 */}
<Routes>
{/* 首页路由 */}
<Route path="/" element={<Home />} />
{/* 关于页面路由 */}
<Route path="/about" element={<About />} />
{/* 404 路由(放在最后) */}
<Route path="*" element={<NotFound />} />
</Routes>
</Router>
);
}- 嵌套路由定义
js
import User from './pages/User';
import Profile from './pages/User/Profile';
import Settings from './pages/User/Settings';
// 在 Routes 中添加
<Route path="/user" element={<User />}>
{/* 嵌套路由,会渲染到 User 组件中的 Outlet 位置 */}
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
{/* 默认子路由 */}
<Route index element={<Profile />} />
</Route>- 子路由出口
js
import { Outlet } from 'react-router-dom';
function User() {
return (
<div>
{/* 子路由内容会在这里显示 */}
<Outlet />
</div>
);
}路由传参方式
三种:query、param、state
- query 方式
js
// 传参
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const param3 = '?id=333&name=Alias'
navigate('/example/router/route3' + param3)
// 获取参数
import { useSearchParams } from 'react-router-dom';
const [searchParams] = useSearchParams();
const id = searchParams.get('id');
const name = searchParams.get('name');- state 方式
js
// 传参
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
navigate('/example/router/route3',{ state: { age: 8, gender: '女' } });
// 获取参数
import { useLocation } from 'react-router-dom';
const location = useLocation();
const { age,gender } = location.state || {};- param 动态路由
js
// 传参
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const param3 = '123'
navigate('/example/router/route2/' + param3);
// 路由单独配置 path
<Route path="route2/:id" element={<Route2 />} />
// 获取参数
import { useParams } from 'react-router-dom';
const { id } = useParams();注意事项
- query 参数和查询参数会显示在 URL 中,适合分享链接的场景
- state 参数不会显示在 URL 中,刷新页面后会丢失
- param 需要修改 path /:id
React Router 核心使用
shell
React Router 是 React 生态中最常用的第三方路由库(由 React Router 团队维护,非 react 核心包内置)。核心是通过声明式组件实现页面跳转,常用有 BrowserRouter(History 模式)、Routes/Route、Link;v5 用 Switch + useHistory,v6+ 用 Routes + useNavigate。实际项目中常配合 React.lazy 做路由级代码分割;权限可在 loader、包装组件或 useEffect 中校验;嵌套路由配合 Outlet 做布局。react 路由不同版本差异
要点速览
shell
v5:兼容类组件 + Hooks,React 16/17 项目最稳
v6:路由组件写法以 Hooks 为主;类组件不能直接用 `useNavigate`,需包一层函数子组件或 HOC,也不再通过 `this.props.history` 注入
v7:与 React 18+、Data API 路线一致;具体 peer 依赖以安装包 `package.json` 的 `peerDependencies` 为准
# 建议
老项目(React ≤17,类组件多):停留在 v5.3(最稳,兼容类组件)
新项目(React 18,全 Hooks):直接用 v6.4+ Data API(现代、性能好)
微服务 / 迁移中:v5 渐进升级到 v6,先改路由组件,再替换 Hooksreact 和 路由版本对比
shell
# 路由版本:v2/v3 → v4 → v5 → v6 → v7
React 路由版本 发布时间 最低 React 版本 主流适配 React 状态
v2 / v3 ~2015–2016 React 0.14+ React 15 废弃(静态路由)
v4 2017-03 React 15+ React 16 旧项目维护
v5 2019-03 React 15+ React 16 / 17 广泛使用
v6 2021-11 React 16.8+(必须 Hooks) React 17 / 18 当前主流
v6.4+(Data API) 2022-09 React 16.8+ React 18 推荐新项目
v7 2025+ React18+ React 18 最新(整合 Remix)不同版本路由的核心差异
shell
# v2 /v3:静态路由时代(已淘汰)
静态配置:集中式路由表(类似 Vue 早期)
核心组件:<Router>、<Route>、<IndexRoute>、<Redirect>
无嵌套路由组件化,配置繁琐
对应 React:0.14 ~ 15.x
# v4:范式革命 —— 动态路由(2017)
彻底组件化:路由即组件,随渲染树动态匹配
移除 <IndexRoute>,用嵌套 <Route> 实现
引入 <Switch>:匹配第一个路径,避免多路由渲染
新增 withRouter:类组件获取路由信息
对应 React:15.x ~ 16.x
# v5:Hooks 完善期(2019)
完全兼容 v4,新增路由 Hooks(React 16.8+)
useHistory、useLocation、useParams、useRouteMatch
更好的 React 16/17 兼容,支持 Suspense 基础用法
类组件仍可用 this.props.history
对应 React:15.x ~ 17.x
# v6:全面现代化(2021,最大变更)
- 组件层面(必改)
<Switch> → <Routes>(功能增强,自动优化匹配)
<Route component={X}> → <Route element={<X />}>(直接传 JSX)
移除 <Redirect> → 新增 <Navigate to="..." />
移除 exact:v6 用路径排名(route ranking)选出最匹配的一条,嵌套路由需配合父级 /* 等写法,不等同于「所有路径必须完全相等」
新增 <Outlet>:嵌套路由出口(类似 Vue <RouterView>)
- Hooks 重命名
useHistory → useNavigate(更简洁,支持相对路径)
useRouteMatch → 移除,用 useMatch 或 useParams 替代
- 嵌套路由简化(v6 最大优势)
<Route path="/user" element={<User />}>
<Route path="profile" element={<Profile />} /> {/* /user/profile */}
</Route>
<div><Outlet /></div>
- v6 嵌套(外层配置,Outlet 渲染子路由)
新增 createBrowserRouter + <RouterProvider>(类似 Next.js 路由配置)
支持 loaders(数据加载)、actions(提交)、errorElement(错误边界)
适配 React 18 并发 / Suspense
# v7:整合 Remix,全栈化(2025)
面向现代栈:典型要求 React 18+、较新的 Node;以官方发布说明为准
继承 v6.4 Data API,默认开启并发渲染兼容
移除旧版兼容代码,体积更小、性能更高v5 和 v6 代码对比
js
/************* 一、路由结构对比 ***************/
// v5
<Switch>
<Route path="/home" component={Home} exact />
<Route path="/user/:id" component={User} />
<Redirect from="/" to="/home" />
</Switch>
// v6
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/user/:id" element={<User />} />
<Route path="/" element={<Navigate to="/home" />} />
</Routes>
/************* 二、编程式导航 ***************/
// v5
import { useHistory } from 'react-router-dom';
function go() { const history=useHistory(); history.push('/home'); }
// v6
import { useNavigate } from 'react-router-dom';
function go() { const navigate=useNavigate(); navigate('/home'); }
/************* 三、嵌套路由 ***************/
// v5(分散式,子组件单独配置)
// App.js
<Route path="/user" component={User} />
// User.js
<Switch>
<Route path="/user/profile" component={Profile} />
</Switch>
// v6(集中式,Outlet 占位)
// App.js
<Route path="/user" element={<User />}>
<Route path="profile" element={<Profile />} />
</Route>
// User.js
<div><Outlet /></div>关于 react 路由钩子
要点速览
shell
React Router v5 /v6.0~6.3:没有官方路由钩子,需要自己封装(v5 /v6 基础版可以自己轻松实现路由钩子,用自定义 Hooks + 监听)
React Router v6.4+:Data API 版,提供 **loader / action / shouldRevalidate** 等与数据、导航相关的入口(权限校验常写在 **loader** 或根布局里,通过 **`redirect()`** 提前返回)
React 路由的设计理念:组件化 > 钩子函数,所以早期一直没提供 beforeEach拓展
shell
# React Router v5(最常用老版本)
你想做权限拦截、页面埋点、跳转前确认,必须自己写:
用 useLocation 监听路由变化
用高阶组件 HOC 包裹页面
用自定义组件做拦截
# React Router v6(现在主流)
6.0 ~ v6.3:仍然没有官方钩子!,和 v5 一样,只能自己实现拦截逻辑。
# React Router v6.4+(现在主流,有钩子)
v6.4+(带 Data API):终于有官方路由守卫 / 钩子!
loader:在渲染前加载/校验(可配合 `redirect` 做登录拦截)
action:路由表单提交等 mutation
shouldRevalidate:控制是否重新验证 loader 数据
errorElement:路由级错误 UI代码实现
v6.4+ 官方原生守卫(推荐新项目)
js
import { createBrowserRouter, RouterProvider, redirect } from "react-router-dom";
const router = createBrowserRouter([
{
path: "/admin",
element: <Admin />,
// 在 loader 里做进入前校验(接近「全局前置守卫」的一种写法)
async loader() {
const isLogin = await checkLogin();
if (!isLogin) throw redirect("/login");
return null;
},
},
]);
function App() {
return <RouterProvider router={router} />;
}v5 /v6 基础版(自己实现全局钩子)
js
/************** 路由拦截(beforeEach) *****************/
// 用自定义守卫组件包裹页面
function AuthGuard({ children }) {
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (!token) {
navigate("/login"); // 拦截
}
}, [location]);
return children;
}
// 使用
<Route
path="/user"
element={
<AuthGuard>
<UserPage />
</AuthGuard>
}
/>
/************** 全局监听路由变化(afterEach) *****************/
import { useLocation } from "react-router-dom";
import { useEffect } from "react";
function useRouteChange() {
const location = useLocation();
useEffect(() => {
console.log("路由变了:", location.pathname);
// 埋点、统计、页面切换动画...
}, [location]);
}