一文吃透 React Router v6:静态 / 动态 / 嵌套路由 + 鉴权 + 懒加载
一、路由基础配置(核心容器与路由表)
React Router v6 中最基础的是路由容器和路由规则定义,核心依赖 BrowserRouter、Routes、Route 三个组件。
1. 路由根容器(BrowserRouter)
所有路由相关逻辑需包裹在路由容器中,代码中 App.jsx 里使用 BrowserRouter(别名 Router)作为根容器,它基于 HTML5 History API 实现路由跳转:
// App.jsx
import { BrowserRouter as Router } from 'react-router-dom'
import Navigation from './components/Navigation'
import RouterConfig from './router/index'
export default function App () {
return (
<Router> {/* 路由根容器,整个应用的路由上下文 */}
<Navigation/> {/* 导航栏(声明式导航) */}
<RouterConfig/> {/* 路由规则配置表 */}
</Router>
)}
2. 路由规则(Routes + Route)
Routes 是路由集合容器,替代了 v5 的 Switch;Route 定义单个路由规则,核心属性:
path:路由路径(支持静态、动态、通配符);element:路径匹配时渲染的组件。
代码中 router/index.jsx 是核心路由配置表:
// router/index.jsx
import { Routes, Route } from 'react-router-dom'
export default function RouterConfig() {
return (
<Suspense fallback={<LoadingFallback/>}>
<Routes> {/* 静态路由:匹配固定路径 */}
<Route path='/' element={<Home/>}/>
<Route path='/about' element={<About/>}/> {/* 其他路由规则... */}
</Routes>
</Suspense>
)}
二、核心路由类型与配置
1. 静态路由
匹配固定的路径,是最基础的路由类型,例如:
<Route path='/' element={<Home/>}/>
<Route path='/about' element={<About/>}/>
<Route path='/login' element={<Login/>}/>
2. 动态路由(带参数的路由)
路径中包含动态参数(如 :id、:productId),用于匹配 “一类路径”(如商品详情、用户详情),通过 useParams 钩子获取参数。
代码示例:
- 路由配置:
// 匹配 /user/123、/user/456 等路径
<Route path='/user/:id' element={<UserProfile/>}/>
// 嵌套的动态路由(见下文嵌套路由)
<Route path='/products' element={<Product/>}>
<Route path=':productId' element={<ProductDetail/>}/>
</Route>
- 获取参数:
// UserProfile.jsx
import { useParams } from "react-router-dom";
export default function UserProfile() {
const { id } = useParams(); // 解构动态参数 id
return <>UserProfile {id}</>;
}
// ProductDetail.jsx
import { useParams } from "react-router-dom";
export default function ProductDetail() {
const { productId } = useParams(); // 解构 productId
return <>ProductDetail {productId}</>;
}
3. 嵌套路由
用于实现 “父页面 + 子页面” 的布局(如产品列表页嵌套产品详情 / 新品页),核心依赖 Outlet 组件(子路由的渲染出口)。
代码示例:
- 路由配置(父路由嵌套子路由):
// router/index.jsx
<Route path='/products' element={<Product/>}>
{/* 子路由:路径拼接为 /products/:productId */}
<Route path=':productId' element={<ProductDetail/>}/>
{/* 子路由:路径拼接为 /products/new */}
<Route path='new' element={<NewProduct/>}/>
</Route>
父组件中定义子路由出口:
// pages/product/index.jsx
import { Outlet } from "react-router-dom";
export default function Product() {
return (
<>
<h1>产品列表</h1>
<Outlet/>
{/* 子路由组件(ProductDetail/NewProduct)会渲染在这里 */}
</>
)}
4. 路由重定向(Navigate)
替代 v5 的 Redirect,用于将某个路径重定向到另一个路径,核心属性 to(目标路径)、replace(是否替换历史记录,避免回退时重复重定向)。
代码示例:
// router/index.jsx
// 将 /old-path 重定向到 /new-path
<Route path='/old-path' element={<Navigate replace to='/new-path'/>}/>
<Route path='/new-path' element={<NewPath/>}/>
// 鉴权组件中未登录时重定向到登录页(见下文路由守卫)
// ProtectRoute.jsx
if(!isLoggedIn){ return <Navigate to='/login'/>; }
5. 404 通配符路由
匹配所有未定义的路径,用于展示 “页面不存在” 提示,路径使用通配符 *。
代码示例:
// router/index.jsx
<Route path='*' element={<NotFound/>}/>
// NotFound.jsx
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
const NotFound = () => {
const navigate = useNavigate(); // 编程式导航钩子
useEffect(() => {
// 6秒后自动跳转到首页
setTimeout(() => navigate('/'), 6000);
},[]);
return <>NotFound</>;
};
export default NotFound;
三、路由进阶能力
1. 路由懒加载(lazy + Suspense)
通过 React 内置的 lazy 实现组件懒加载(按需加载),结合 Suspense 指定加载中的占位组件(Loading 效果),优化首屏加载性能。
代码示例:
// router/index.jsx
import { lazy, Suspense } from 'react';
import LoadingFallback from '../components/LoadingFallback';
// 懒加载组件(替代直接 import)
const Home = lazy(() => import('../pages/Home'));
const About = lazy(() => import('../pages/About'));
const Pay = lazy(() => import('../pages/Pay'));
export default function RouterConfig() {
return (
// Suspense 包裹路由表,fallback 为加载中占位组件
<Suspense fallback={<LoadingFallback/>}>
<Routes>{/* 路由规则 */}</Routes>
</Suspense> );
}
2. 路由守卫(鉴权路由)
自定义组件实现路由级别的权限控制(如登录鉴权),核心逻辑是:判断权限 → 有权限则渲染子组件,无权限则重定向。
代码示例:
// ProtectRoute.jsx
import { Navigate } from "react-router-dom";
export default function ProtectRoute ({children}) {
// 从 localStorage 判断登录状态
const isLoggedIn = localStorage.getItem('isLogin') === 'true';
if(!isLoggedIn){
// 未登录:重定向到登录页
return <Navigate to='/login'/>;
}
// 已登录:渲染子组件(如 Pay)
return <>{children}</>;
}
// 路由配置中使用鉴权组件
<Route path='/pay' element={
<ProtectRoute>
<Pay/> {/* 需要鉴权的组件 */}
</ProtectRoute>
}/>
3. 导航相关
(1)声明式导航(Link)
替代 <a> 标签,实现无刷新跳转,核心属性 to 指定目标路径。
代码示例:
// Navigation.jsx
import { Link } from "react-router-dom";
export default function Navigation() {
return (
<nav>
<ul>
<li><Link to='/' className={isActive('/')}>Home</Link></li>
<li><Link to='/about'>About</Link></li>
</ul>
</nav>
);}
(2)编程式导航(useNavigate)
通过钩子实现代码触发的跳转(如按钮点击、延时跳转),替代 v5 的 useHistory。
代码示例:
// NotFound.jsx
import { useNavigate } from "react-router-dom";
const NotFound = () => {
const navigate = useNavigate();
useEffect(() => {
setTimeout(() => navigate('/'), 6000); // 6秒后跳转到首页
},[]);
return <>NotFound</>;
};
(3)路由激活状态判断(useResolvedPath + useMatch)
用于实现导航栏的 “当前页高亮”,useResolvedPath 解析目标路径,useMatch 匹配当前路由是否与目标路径一致。
代码示例:
// Navigation.jsx
import { useResolvedPath,useMatch } from "react-router-dom";
export default function Navigation() {
const isActive = (to) => {
const resolvePath = useResolvedPath(to); // 解析目标路径 // 匹配当前路由是否与目标路径完全一致(end: true)
const match = useMatch({
path: resolvePath.pathname,
end: true });
return match ? 'active' : ''; // 匹配则返回激活类名
};
return (
<li><Link to='/' className={isActive('/')}>Home</Link></li>
);
}
总结
React Router v6 的核心设计理念是 “声明式”+“组件化”,所有路由能力都通过组件 / 钩子实现,核心要点:
- 路由容器:
BrowserRouter包裹整个应用; - 路由规则:
Routes+Route定义路径与组件的映射; - 进阶能力:嵌套路由(
Outlet)、动态路由(useParams)、懒加载(lazy+Suspense)、鉴权(自定义守卫组件)、导航(Link/useNavigate)是高频使用的特性; - 兼容性:v6 对比 v5 有较多 API 变更(如
Switch→Routes、useHistory→useNavigate),需注意版本差异。以下结合提供的代码,详细讲解 React Router v6(react-router-dom)中核心的路由概念与配置方法: