Skip to content

React 文档

导读与全书目录表:见同目录 01-React 入门:简介·特性与设计范式.md 开头。


react 路由

路由核心概念

js
<Router>:路由的根组件,通常使用 BrowserRouter
<Routes>:路由容器,内部包含多个 <Route>
<Route>:定义路由规则,path 是路径,element 是要渲染的组件
<Link>:导航链接,类似 <a> 标签但不会刷新页面
<Outlet>:用于嵌套路由,显示子路由的内容

路由示例

  1. 基础路由定义
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>
  );
}
  1. 嵌套路由定义
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>
  1. 子路由出口
js
import { Outlet } from 'react-router-dom';

function User() {
  return (
    <div>
      {/* 子路由内容会在这里显示 */}
      <Outlet />
    </div>
  );
}

路由传参方式

三种:query、param、state

  1. 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');
  1. 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 || {};
  1. 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,先改路由组件,再替换 Hooks

react 和 路由版本对比

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]);
}