在学习react的过程中,"如何在不同页面之间跳转" 是绕不开的问题。react-router-dom
作为 React 生态中处理前端路由的核心库,能帮我们轻松实现页面导航。
什么是路由?从前后端路由的区别说起
在学习react-router-dom
之前,我们需要先明确 "路由" 的本质:路由是 "路径" 与 "资源 / 页面" 的映射关系。简单说,就是 "访问某个路径时,展示对应的内容"。但前端路由和后端路由的作用场景有本质区别。
(1)后端路由:传统 Web 开发的路径映射
早期的 Web 开发中,路由由后端控制,称为 "后端路由"。其工作流程是:
- 用户在浏览器输入路径(如
/about
),发送请求到服务器; - 服务器根据路径匹配对应的处理逻辑,返回完整的 HTML 页面;
- 浏览器接收并渲染新页面,完成跳转。
特点:
- 每次跳转都需要重新请求服务器,返回全新 HTML;
- 前后端耦合度高:后端不仅要处理数据逻辑,还要负责页面渲染;
- 示例:
/
对应首页 HTML,/user
对应用户页 HTML,路径直接映射物理页面。
前端路由:单页应用(SPA)的页面切换
随着前后端分离和单页应用(SPA)的普及,前端路由应运而生。在 SPA 中,整个应用只有一个 HTML 页面,前端路由负责 "在同一个页面内,根据不同路径展示不同组件",无需重新请求服务器。
工作流程:
- 用户点击导航(如 "关于我们"),前端路由捕获路径变化(如
/about
); - 前端框架(如 React)根据路径匹配对应的组件(如
About
组件); - 页面局部更新,展示匹配的组件,URL 同步变化但不刷新页面。
特点:
- 无需重新请求服务器,跳转更流畅,用户体验接近原生应用;
- 路径与前端组件直接映射,由前端完全控制;
- 核心依赖:
react-router-dom
就是 React 生态中实现这一功能的库。
为什么需要 react-router-dom?它在 React 生态中的作用
React 本身只负责组件的渲染和状态管理,不包含 "路径与组件映射" 的功能。react-router-dom
作为 React 官方推荐的路由库,专门解决单页应用中的导航问题,核心作用是:
- 管理路径与组件的映射关系(如
/
对应Home
组件,/about
对应About
组件); - 实现无刷新页面切换,保持应用状态不丢失;
- 支持动态路径参数(如
/user/:id
)、嵌套路由(如/products/:id
)等复杂场景。
目前最新稳定版为7.6.3
,版本号的含义需要了解:
- 主版本号(7):大版本更新可能包含不兼容的 API 变更(如从 v6 到 v7 可能有语法调整);
- 次版本号(6):新增功能但保持向后兼容(升级后旧代码仍可运行);
- 修订号(3):修复 bug 或性能优化,无功能变更。
react-router-dom 的核心用法:从安装到基础配置
(1)安装 react-router-dom
首先通过 npm 安装库(确保已创建 React 项目):
bash
npm install react-router-dom
(2)核心组件:构建路由的 "三要素"
react-router-dom
的基础使用依赖三个核心组件,初学者需牢记它们的作用:
组件名 | 作用 | 常用场景 |
---|---|---|
BrowserRouter |
路由的 "容器",包裹整个应用的路由配置 | 作为最外层组件,仅需一个 |
Routes |
路由规则的 "容器",管理所有Route 组件 |
包裹多个Route ,内部只能放Route |
Route |
定义 "路径 - 组件" 的映射关系 | 每个Route 对应一个页面 |
(3)基础配置:第一个路由示例
以下是一个最简单的路由配置,实现 "首页" 和 "关于页" 的切换:
jsx
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './pages/Home'; // 首页组件
import About from './pages/About'; // 关于页组件
function App() {
return (
{/* 1. 用Router包裹整个路由系统(别名BrowserRouter为Router,简化写法) */}
<Router>
{/* 2. 用Routes包裹所有路由规则 */}
<Routes>
{/* 3. 用Route定义路径与组件的映射:path是路径,element是对应的组件 */}
<Route path="/" element={<Home />} /> {/* 根路径对应Home组件 */}
<Route path="/about" element={<About />} /> {/* /about对应About组件 */}
</Routes>
</Router>
);
}
export default App;
组件代码示例(简单的页面组件):
jsx
// src/pages/Home.jsx
const Home = () => {
return <h1>首页</h1>;
};
export default Home;
// src/pages/About.jsx
const About = () => {
return <h1>关于我们</h1>;
};
export default About;
效果:
- 访问
http://localhost:5173
时,页面展示 "首页";

- 访问
http://localhost:5173/about
时,页面展示 "关于我们";

- 路径变化时,页面不刷新,仅局部更新组件。
动态路由参数:如何获取路径中的变量
在实际开发中,我们经常需要根据动态路径展示不同内容(如 "用户详情页",路径为/user/123
,其中123
是用户 ID)。react-router-dom
通过 "动态参数" 实现这一功能。
(1)定义动态路径
在Route
的path
中,用:参数名
表示动态参数(如:id
):
jsx
// App.jsx中添加用户详情页路由
import UserProfile from './pages/UserProfile';
<Routes>
{/* 其他路由... */}
<Route path="/user/:id" element={<UserProfile />} /> {/* :id是动态参数 */}
</Routes>
(2)用 useParams 钩子获取参数
在组件中,通过react-router-dom
提供的useParams
钩子,可以轻松获取动态参数:
jsx
// src/pages/UserProfile.jsx
import { useParams, useEffect } from 'react-router-dom';
const UserProfile = () => {
// 解构获取path中的id参数(参数名与path中:后的名称一致)
const { id } = useParams();
useEffect(() => {
// 实际开发中,可根据id请求用户详情数据
console.log('当前用户ID:', id); // 访问/user/123时,输出123
}, [id]); // 依赖id,当id变化时重新执行
return <h1>用户详情页:ID={id}</h1>;
};
export default UserProfile;
效果:
- 访问
/user/12
,页面展示 "用户详情页:ID=12";

- 访问
/user/45
,页面展示 "用户详情页:ID=45",无需额外配置。

嵌套路由:实现页面内的子导航
在复杂应用中,我们常需要 "父页面包含子页面" 的结构(如 "产品列表页" 包含 "产品详情""新增产品" 等子页面)。react-router-dom
的嵌套路由可以完美实现这一场景。
(1)配置嵌套路由
嵌套路由的核心是 "在父Route
中嵌套子Route
",并通过Outlet
组件指定子组件的展示位置:
jsx
// App.jsx中配置产品相关的嵌套路由
import Products from './pages/Products';
import ProductDetails from './pages/Products/ProductDetails';
import NewProduct from './pages/Products/NewProduct';
<Routes>
{/* 其他路由... */}
{/* 父路由:path为/products,对应Products组件 */}
<Route path="/products" element={<Products />}>
{/* 子路由:路径是相对路径(无需加/products前缀) */}
<Route path=":productId" element={<ProductDetails />} /> {/* 产品详情:/products/1 */}
<Route path="new" element={<NewProduct />} /> {/* 新增产品:/products/new */}
</Route>
</Routes>
(2)用 Outlet 指定子组件位置
父组件(Products
)中需要通过Outlet
组件定义 "子组件在哪里展示",类似 "占位符":
jsx
// src/pages/Products.jsx
import { Outlet } from 'react-router-dom';
const Products = () => {
return (
<div>
<h1>产品列表(父页面)</h1>
{/* 子路由对应的组件会在这里展示 */}
<Outlet />
</div>
);
};
export default Products;
(3)子组件实现
子组件(ProductDetails
和NewProduct
)只需正常定义,无需特殊配置:
jsx
// src/pages/Products/ProductDetails.jsx
import { useParams } from 'react-router-dom';
const ProductDetails = () => {
const { productId } = useParams(); // 获取产品ID
return <p>产品详情:ID={productId}</p>;
};
export default ProductDetails;
// src/pages/Products/NewProduct.js
const NewProduct = () => {
return <p>新增产品表单</p>;
};
export default NewProduct;
效果:
- 访问
/products
时,页面展示 "产品列表(父页面)",Outlet
位置为空;

- 访问
/products/1
时,Outlet
位置展示 "产品详情:ID=1";

- 访问
/products/new
时,Outlet
位置展示 "新增产品表单"。

路由导航:用 Link 组件实现无刷新跳转
在页面中,我们需要通过 "链接" 实现路径切换,react-router-dom
提供Link
组件替代传统的<a>
标签,避免跳转时刷新页面:
jsx
// 在任意组件中引入Link(以Home组件为例)
import { Link } from 'react-router-dom';
const Home = () => {
return (
<div>
<h1>首页</h1>
{/* 用Link实现导航,to属性对应目标路径 */}
<Link to="/about">去关于页</Link>
<br />
<Link to="/user/123">去用户123的详情页</Link>
<br />
<Link to="/products/new">去新增产品页</Link>
</div>
);
};
为什么不用
<a>
标签?
传统的<a href="/about">
会触发页面刷新,导致 React 应用状态丢失;而Link
组件仅修改 URL 和展示的组件,不刷新页面,保持应用状态。


注意事项
-
路径匹配规则:
path
区分大小写(/About
和/about
是两个不同路径);- 子路由的
path
是相对路径(基于父路由的path
,无需重复父路径)。
-
useParams 的依赖 :
组件中使用
useParams
获取的参数,需添加到useEffect
的依赖数组中(如[id]
),确保参数变化时重新执行逻辑。 -
Router 的层级 :
BrowserRouter
(即Router
)必须包裹所有路由相关组件(包括Link
、useParams
等),否则会报错。通常放在App
组件的最外层。 -
版本兼容问题 :
react-router-dom
的 v6 和 v7 语法基本兼容,但 v5 及之前版本差异较大(如 v5 用Switch
替代Routes
),初学者需注意自己安装的版本。
掌握 react-router-dom,构建完整的 React 应用
react-router-dom
是 React 单页应用中处理导航的核心工具,其核心价值是 "在不刷新页面的情况下,实现路径与组件的映射"。本文从路由的基础概念出发,讲解了:
- 前后端路由的区别,理解前端路由的必要性;
react-router-dom
的安装和核心组件(Router
、Routes
、Route
)的使用;- 动态参数(
useParams
)和嵌套路由(Outlet
)的实战配置; - 用
Link
组件实现无刷新跳转。