Ⅰ.基础路由配置
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
// 1. 定义路由配置
const router = createBrowserRouter([
{
path: '/',
element: <HomePage />,
},
{
path: '/about',
element: <AboutPage />,
},
]);
// 2. 挂载路由
ReactDOM.createRoot(root).render(
<RouterProvider router={router} />
);
Ⅱ.嵌套路由
1.基础嵌套结构
通过<Outlet>实现布局嵌套
const router = createBrowserRouter([
{
path: '/',
element: <Layout />, // 父级布局
children: [
{
index: true, // 默认路由
element: <Dashboard />,
},
{
path: 'profile',
element: <Profile />,
},
{
path: 'settings',
element: <Settings />,
},
],
},
]);
// Layout 组件使用 Outlet
function Layout() {
return (
<div>
<header>导航栏</header>
<main>
<Outlet /> {/* 子路由渲染位置 */}
</main>
<footer>页脚</footer>
</div>
);
}
2.多级嵌套
const router = createBrowserRouter([
{
path: '/admin',
element: <AdminLayout />,
children: [
{
path: 'users',
element: <UserManagementLayout />,
children: [
{
path: 'list',
element: <UserList />,
},
{
path: 'create',
element: <UserCreate />,
},
],
},
],
},
]);
Ⅲ.动态路由
1.定义动态参数
const router = createBrowserRouter([
{
path: '/users/:userId',
element: <UserDetail />,
},
{
path: '/products/:category/:id',
element: <ProductDetail />,
},
]);
// 组件中获取参数
import { useParams } from 'react-router-dom';
function UserDetail() {
const { userId } = useParams(); // { userId: "123" }
return <div>用户ID: {userId}</div>;
}
function ProductDetail() {
const { category, id } = useParams(); // { category: "electronics", id: "456" }
return <div>分类: {category}, ID: {id}</div>;
}
2.可选参数和通配符
const router = createBrowserRouter([
{
path: '/docs/:section?', // 可选参数
element: <Documentation />,
},
{
path: '/files/*', // 通配符匹配所有子路径
element: <FileBrowser />,
},
]);
Ⅳ.编程式导航
1.使用useNavigate
import { useNavigate } from 'react-router-dom';
function NavigationExample() {
const navigate = useNavigate();
const handleNavigation = () => {
// 基础导航
navigate('/target-path');
// 带状态导航
navigate('/dashboard', {
state: { from: 'login' },
replace: true, // 替换历史记录
});
// 相对路径导航
navigate('../parent'); // 上一级
navigate('./child'); // 当前路径下的子路径
};
return (
<div>
<button onClick={() => navigate(-1)}>返回</button>
<button onClick={() => navigate(1)}>前进</button>
<button onClick={handleNavigation}>跳转</button>
</div>
);
}
2.重定向组件
import { Navigate } from 'react-router-dom';
function ProtectedRoute({ isAuthenticated, children }) {
return isAuthenticated ? children : <Navigate to="/login" replace />;
}
// 使用示例
<Route
path="/admin"
element={
<ProtectedRoute isAuthenticated={user.isAdmin}>
<AdminPanel />
</ProtectedRoute>
}
/>
Ⅴ.路由守卫
1.高阶组件形式
import { Navigate, useLocation } from 'react-router-dom';
function RequireAuth({ children, roles = [] }) {
const auth = useAuth();
const location = useLocation();
if (!auth.user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
if (roles.length > 0 && !roles.includes(auth.user.role)) {
return <Navigate to="/unauthorized" replace />;
}
return children;
}
// 使用示例
const router = createBrowserRouter([
{
path: '/admin',
element: (
<RequireAuth roles={['admin', 'superadmin']}>
<AdminPanel />
</RequireAuth>
),
},
]);
2.Loader拦截
// 权限校验 Loader
export async function adminLoader({ request }) {
const user = await getCurrentUser();
if (!user) {
throw redirect('/login');
}
if (user.role !== 'admin') {
throw redirect('/unauthorized');
}
return { user };
}
// 路由配置
const router = createBrowserRouter([
{
path: '/admin',
element: <AdminPanel />,
loader: adminLoader, // 路由级别权限控制
},
]);
Ⅵ.特殊路由配置
1.404页面
const router = createBrowserRouter([
// ...其他路由
{
path: '*',
element: <NotFoundPage />,
},
]);
Ⅶ.数据加载
1.Loader数据预加载
import { json } from 'react-router-dom';
// 用户详情页 Loader
export async function userLoader({ params, request }) {
const userId = params.userId;
try {
const user = await fetchUser(userId);
const posts = await fetchUserPosts(userId);
return json({ user, posts });
} catch (error) {
throw new Response('用户不存在', { status: 404 });
}
}
// 组件中使用数据
import { useLoaderData } from 'react-router-dom';
function UserProfile() {
const { user, posts } = useLoaderData();
return (
<div>
<h1>{user.name}</h1>
{posts.map(post => (
<article key={post.id}>{post.title}</article>
))}
</div>
);
}
2.Action数据处理
// 表单提交 Action
export async function userAction({ request, params }) {
const formData = await request.formData();
const intent = formData.get('intent');
switch (intent) {
case 'update':
return updateUser(params.userId, formData);
case 'delete':
return deleteUser(params.userId);
default:
throw new Error('未知操作');
}
}
// 表单组件
function UserForm() {
return (
<Form method="post">
<input type="text" name="name" />
<button type="submit" name="intent" value="update">
更新
</button>
<button type="submit" name="intent" value="delete">
删除
</button>
</Form>
);
}
Ⅷ.高级特性
1.懒加载路由
const router = createBrowserRouter([
{
path: '/dashboard',
lazy: () => import('./routes/Dashboard'), // 动态导入
},
{
path: '/admin',
lazy: async () => {
const { AdminLayout, adminLoader } = await import('./routes/Admin');
return {
Component: AdminLayout,
loader: adminLoader
};
},
},
]);
2.错误边界处理
// 路由级别错误处理
const router = createBrowserRouter([
{
path: '/',
element: <Root />,
errorElement: <ErrorBoundary />, // 错误边界组件
children: [
{
path: 'users/:userId',
element: <UserDetail />,
errorElement: <UserError />, // 子路由错误处理
},
],
},
]);
// 错误边界组件
function ErrorBoundary() {
const error = useRouteError();
return (
<div>
<h1>出错了!</h1>
<p>{error.statusText || error.message}</p>
</div>
);
}
3.滚动恢复
import { ScrollRestoration } from 'react-router-dom';
function Root() {
return (
<>
<ScrollRestoration /> {/* 自动恢复滚动位置 */}
<Outlet />
</>
);
}
Ⅸ.最佳实践
1.项目组织结构
src/
├── routes/ # 路由组件
│ ├── index.tsx # 首页
│ ├── about/
│ │ ├── index.tsx
│ │ └── team.tsx
│ └── users/
│ ├── index.tsx
│ ├── [id].tsx # 动态路由
│ └── create.tsx
├── components/ # 共享组件
├── layouts/ # 布局组件
├── router/ # 路由配置
│ └── index.ts
└── main.tsx
2.类型安全配置
// router/types.ts
import { RouteObject } from 'react-router-dom';
export interface AppRoute extends RouteObject {
meta?: {
title?: string;
requiresAuth?: boolean;
roles?: string[];
};
children?: AppRoute[];
}
// router/config.ts
export const routes: AppRoute[] = [
{
path: '/',
element: <Home />,
meta: { title: '首页' },
},
];
3.性能优化技巧
// 1. 代码分割
const LazyComponent = lazy(() => import('./HeavyComponent'));
// 2. 预加载
<Link to="/dashboard" onMouseEnter={() => preloadDashboard()} />
// 3. 记忆化导航
const navigate = useNavigate();
const memoizedNavigate = useCallback((path: string) => {
navigate(path);
}, [navigate]);