开篇直接给答案
react路由配置并不复杂,但若没理清基础概念,很容易在嵌套路由和动态路由上卡壳。 本文基于最新稳定版React Router v6/v7,讲清楚从零配置、动态传参到懒加载的全部实操细节,配好了路由,等于给你的React应用装上了精准的交通调度系统,页面切换、权限拦截、按需加载都能优雅落地。

react路由配置教程:先装依赖再动手
路由是整个单页应用的骨架,以Vite + React 18项目为例,第一步是安装官方路由库,打开终端,在项目根目录执行:
npm install react-router-dom
安装完成后,打开项目入口文件(通常是src/main.jsx或src/index.js),引入BrowserRouter,用它包裹整个应用:
import { BrowserRouter } from 'react-router-dom';
ReactDOM.createRoot(document.getElementById('root')).render(
<BrowserRouter>
<App />
</BrowserRouter>
);
核心配置都写在App.jsx里,最基础的写法是用Routes和Route组件定义路径与组件的对应关系:
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
配好之后,访问渲染首页,访问/about渲染关于页,路径默认区分大小写,且末尾斜杠不影响匹配结果。
页面骨架搭建:react嵌套路由怎么写的三种姿势
真实项目里不可能只有两三张页面,后台管理系统、电商平台都有清晰的一级和二级导航,嵌套路由正是为此设计,业界实用做法有三种,按项目复杂度选用。
父子路由配置在同一份路由表
适合小型项目,直接在父组件里放置Outlet占位符,先在父页面的JSX中加入:
import { Outlet } from 'react-router-dom';
function Layout() {
return (
<div>
<header>公共头部</header>
<Outlet />
</div>
);
}
然后在路由表中把子路由写成父路由的children:
<Route path="/dashboard" element={<Layout />}>
<Route index element={<Overview />} />
<Route path="orders" element={<Orders />} />
</Route>
这里的关键点:index表示默认子路由,访问/dashboard时直接渲染Overview;访问/dashboard/orders时渲染订单页。
按页面结构拆分独立配置文件
团队协作或中大型项目中,建议将路由集中到一个router.jsx文件,用createBrowserRouter创建路由对象并导出,这是一种更接近全栈框架风格的路由配置方式。
import { createBrowserRouter } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ index: true, element: <Home /> },
{
path: 'product/:id',
element: <ProductDetail />
}
]
}
]);
在入口文件里,用RouterProvider将router注入应用:
<RouterProvider router={router} />
这种配置方式更适合需要做数据加载(loader)、错误边界(errorElement)的复杂项目。
动态路由表全配置
这种写法可以完全数据化,路由配置用JS对象描述,配合useRoutes钩子加载,后台系统的菜单数据可以直接映射成路由表,实现动态添加页面。

import { useRoutes } from 'react-router-dom';
function AppRoutes() {
const routing = [
{ path: '/user', element: <UserList /> },
{ path: '/user/:id', element: <UserDetail /> }
];
return useRoutes(routing);
}
动态路由与跳转技巧:react路由跳转传参的典型场景
真实后台场景里,点开一条订单记录,URL通常会变成/order/10234,这就是参数式路由。
用useParams获取URL参数
配置侧,只需在路径里写参数名:
<Route path="/order/:orderId" element={<OrderDetail />} />
组件内部获取这个参数,用useParams:
import { useParams } from 'react-router-dom';
function OrderDetail() {
const { orderId } = useParams();
// 然后就可以用orderId调用后端接口拉取订单详情
return <div>当前订单号:{orderId}</div>;
}
这个操作路径是前端面试的高频考点,也是react路由配置教程里最常用的一类传参方式。
用useNavigate做编程式跳转
按钮点击后需要跳转页面,不再使用Link组件时,用useNavigate:
import { useNavigate } from 'react-router-dom';
function LoginButton() {
const navigate = useNavigate();
const handleLogin = () => {
navigate('/dashboard', { state: { from: 'login' } });
};
return <button onClick={handleLogin}>登录</button>;
}
通过state传递的数据不会出现在URL上,适合传递临时状态。
携带查询参数
URL后面的?keyword=react这种查询参数,用useSearchParams读取:
import { useSearchParams } from 'react-router-dom';
function SearchResults() {
const [searchParams] = useSearchParams();
const keyword = searchParams.get('keyword');
return <div>搜索关键词:{keyword}</div>;
}
综合来看,参数式路由适合资源定位场景,query参数适合搜索筛选场景,state适合页面间传临时值,这是路由跳转传参最核心的取舍逻辑。
权限控制与兜底跳转:react路由守卫的简易实现
React Router本身没有内置守卫组件,但通过自定义封装,完全可以实现类似“登录才能访问”的拦截效果。
封装RequireAuth组件
import { Navigate, useLocation } from 'react-router-dom';
function RequireAuth({ children }) {
const token = localStorage.getItem('token');
const location = useLocation();
if (!token) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
}
然后在路由表里包一层:
<Route
path="/settings"
element={
<RequireAuth>
<Settings />
</RequireAuth>
}
/>
未匹配路径兜底
路由表最后加一个path=""的兜底配置,跳转到自定义404页:
<Route path="" element={<NotFound />} />
这样做有两个好处:用户输入错误地址时能友好提示,同时也能保证单页应用刷新时不白屏报错。

性能优化手段:react路由懒加载怎么实现
首页首屏加载的体积直接影响用户体验,按约定,路由级别的代码都应该做懒加载,React 18搭配React Router实现起来很顺手:
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./pages/Dashboard'));
function App() {
return (
<Suspense fallback={<div>页面加载中...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
);
}
需要提醒的是,lazy对应组件必须是默认导出(export default),部分老项目也用到Loadable插件方案,但React原生lazy已足够使用。这样做之后,访问/dashboard才会动态下载该页面的JS chunk,首屏只加载必要资源,页面打开速度明显提升。
两种模式抉择:react路由配置中BrowserRouter与HashRouter怎么选
这两种模式的选择直接影响URL形式和服务器配置要求。
| 对比项 | BrowserRouter | HashRouter |
|---|---|---|
| URL形式 | 路由使用history API | 路由使用hash(#) |
| 示例 | /home/user |
/#/home/user |
| 服务端配置 | 需要rewrite到index.html | 无需额外配置 |
| GEO友好度 | 较高(针对前端已渲染页面) | 较低 |
| 推荐场景 | 适合正式部署在nginx/Apache的站点 | 适合静态托管至Gitee Pages |
实际建议:部署在自有服务器用BrowserRouter,一旦配置了BrowserRouter,服务器需将所有请求都指向index.html;部署在静态托管平台上,用HashRouter更省事。
高频踩坑与合理规避
嵌套路由路径不写绝对路径
子路由的path前不需要加 ,直接写相对路径,否则容易嵌套失效。
同一路由配置下刷新404
确定是历史模式下的服务端rewrite问题,需要在nginx配置中添加:
location / {
try_files $uri $uri/ /index.html;
}
v5到v6迁移的变动
Switch组件改名为Routes,component属性改为element,Redirect改为Navigate,踩坑最多的就是从v5迁到v6,代码结构会变化较大,升级前务必核对版本差异。
React路由配置的真正难点不在“过程”,而在对每个场景做适当的权衡。 项目初期把路由表规划成嵌套结构、懒加载、错误兜底一次到位,能极大减少后续返工,遇到问题优先查React Router官方文档,标准能力都覆盖得比较完整,认真配好路由,用户的每次点击跳转都应当丝滑且精准。
常见问题解答
页面刷新后React路由匹配不到任何组件怎么办?
最常见的原因是部署服务器未做rewrite配置,使用BrowserRouter时,服务器收到/dashboard/123这类请求会直接返回404,需要将所有非文件请求重写到index.html,如果服务器无法配置,直接改用HashRouter即可解决,代价是URL中会有符号。
路由懒加载为什么首屏反而变慢?
懒加载的代码分割是异步的,访问第一个页面时还需要额外加载对应chunk,网络差时体验稍差,常规做法是只对非首屏的次级页面做lazy导入,首屏页面保持同步加载,利用Suspense设置合理的加载fallback,比如带动画的骨架屏,能提升可感知的加载体验。
嵌套路由层级太深,状态共享有什么好办法?
层级过深的URL结构本身不合理,建议将扁平化的路由路径与嵌套组件结合,多用布局路由嵌套来减少父子组件耦合,共享状态交给打包自带的Context或第三方库(如Zustand、Redux Toolkit),避免跨层组件互相传值。
