# 路由设计
> **文档版本**:v1.1
> **最后更新**:2025-01-18
---
## 目录
1. [路由结构](#1-路由结构)
2. [路由配置](#2-路由配置)
3. [路由守卫](#3-路由守卫)
4. [路由辅助函数](#4-路由辅助函数)
---
## 1. 路由结构
### 1.1 路由常量定义
```typescript
// src/constants/routes.ts
export const ROUTES = {
// 公开页面
HOME: "/",
LOGIN: "/login",
REGISTER: "/register",
// 项目管理
PROJECTS: "/projects",
PROJECT_DETAIL: "/projects/:projectId",
// 编辑器
EDITOR: "/editor/:projectId",
// 设置
SETTINGS: "/settings",
PROFILE: "/settings/profile",
PREFERENCES: "/settings/preferences",
// 其他
NOT_FOUND: "/404",
} as const;
```
### 1.2 路由层级
```
/ # 首页
├── /login # 登录页
├── /register # 注册页
├── /projects # 项目列表
│ └── /:projectId # 项目详情/编辑器
├── /settings # 设置
│ ├── /profile # 个人资料
│ └── /preferences # 偏好设置
└── /404 # 404 页面
```
---
## 2. 路由配置
### 2.1 Router 配置
```typescript
// src/app/Router.tsx
import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';
import { lazy, Suspense } from 'react';
import { ROUTES } from '@constants/routes';
import { LoadingSpinner } from '@components/common';
import { ProtectedRoute } from './ProtectedRoute';
import { AppLayout } from '@components/layout/AppLayout';
// 懒加载页面
const HomePage = lazy(() => import('@/pages/HomePage'));
const LoginPage = lazy(() => import('@/pages/LoginPage'));
const ProjectsPage = lazy(() => import('@/pages/ProjectsPage'));
const ProjectPage = lazy(() => import('@/pages/ProjectPage'));
const NotFoundPage = lazy(() => import('@/pages/NotFoundPage'));
// 页面加载 Wrapper
function PageLoader({ children }: { children: React.ReactNode }) {
return (
}>
{children}
);
}
const router = createBrowserRouter([
{
path: ROUTES.HOME,
element: ,
},
{
path: ROUTES.LOGIN,
element: ,
},
{
path: ROUTES.PROJECTS,
element: (
),
},
{
path: ROUTES.PROJECT_DETAIL,
element: (
),
},
{
path: '*',
element: ,
},
]);
export function Router() {
return ;
}
```
### 2.2 嵌套路由示例
```typescript
// 如果需要嵌套路由
const router = createBrowserRouter([
{
path: '/',
element: ,
children: [
{
index: true,
element: ,
},
{
path: 'projects',
element: ,
children: [
{
index: true,
element: ,
},
{
path: ':projectId',
element: ,
},
],
},
],
},
]);
```
---
## 3. 路由守卫
### 3.1 认证守卫
```typescript
// src/app/ProtectedRoute.tsx
import { Navigate, Outlet, useLocation } from 'react-router-dom';
import { useAppStore } from '@stores/appStore';
import { ROUTES } from '@constants/routes';
export function ProtectedRoute() {
const user = useAppStore((state) => state.user);
const location = useLocation();
if (!user) {
// 保存当前位置,登录后跳转回来
return ;
}
return ;
}
```
### 3.2 权限守卫
```typescript
// src/app/RoleGuard.tsx
import { Navigate } from 'react-router-dom';
import { useAppStore } from '@stores/appStore';
import { ROUTES } from '@constants/routes';
interface RoleGuardProps {
children: React.ReactNode;
allowedRoles: string[];
}
export function RoleGuard({ children, allowedRoles }: RoleGuardProps) {
const user = useAppStore((state) => state.user);
if (!user || !allowedRoles.includes(user.role)) {
return ;
}
return <>{children}>;
}
// 使用示例
```
### 3.3 登录后重定向
```typescript
// src/pages/LoginPage.tsx
import { useNavigate, useLocation } from 'react-router-dom';
import { useAppStore } from '@stores/appStore';
import { ROUTES } from '@constants/routes';
function LoginPage() {
const navigate = useNavigate();
const location = useLocation();
const setUser = useAppStore((state) => state.setUser);
const handleLogin = async (credentials: LoginCredentials) => {
const user = await loginApi(credentials);
setUser(user);
// 登录后跳转到之前的页面,或默认跳转到项目列表
const from = location.state?.from?.pathname || ROUTES.PROJECTS;
navigate(from, { replace: true });
};
return ;
}
```
---
## 4. 路由辅助函数
### 4.1 路径生成函数
```typescript
// src/constants/routes.ts
// 路由辅助函数
export const getProjectPath = (projectId: string) => `/projects/${projectId}`;
export const getEditorPath = (projectId: string) => `/editor/${projectId}`;
export const getSettingsPath = (tab?: string) =>
tab ? `/settings/${tab}` : '/settings';
// 使用示例
import { useNavigate } from 'react-router-dom';
import { getProjectPath } from '@constants/routes';
function ProjectCard({ project }: { project: Project }) {
const navigate = useNavigate();
const handleClick = () => {
navigate(getProjectPath(project.id));
};
return
{project.name}
;
}
```
### 4.2 路由参数 Hook
```typescript
// src/hooks/useProjectRoute.ts
import { useParams, useNavigate } from 'react-router-dom';
import { ROUTES } from '@constants/routes';
export function useProjectRoute() {
const { projectId } = useParams<{ projectId: string }>();
const navigate = useNavigate();
const goToProject = (id: string) => {
navigate(`/projects/${id}`);
};
const goToProjects = () => {
navigate(ROUTES.PROJECTS);
};
return {
projectId,
goToProject,
goToProjects,
};
}
// 使用示例
function ProjectPage() {
const { projectId, goToProjects } = useProjectRoute();
if (!projectId) {
return ;
}
return (
);
}
```
### 4.3 查询参数处理
```typescript
// src/hooks/useQueryParams.ts
import { useSearchParams } from 'react-router-dom';
export function useQueryParams() {
const [searchParams, setSearchParams] = useSearchParams();
const getParam = (key: string) => searchParams.get(key);
const setParam = (key: string, value: string) => {
const newParams = new URLSearchParams(searchParams);
newParams.set(key, value);
setSearchParams(newParams);
};
const removeParam = (key: string) => {
const newParams = new URLSearchParams(searchParams);
newParams.delete(key);
setSearchParams(newParams);
};
return {
getParam,
setParam,
removeParam,
searchParams,
};
}
// 使用示例
function ProjectsPage() {
const { getParam, setParam } = useQueryParams();
const filter = getParam('filter') || 'all';
const handleFilterChange = (newFilter: string) => {
setParam('filter', newFilter);
};
return (
);
}
```
---
## 5. 路由最佳实践
### 5.1 懒加载
```typescript
// ✅ 推荐:使用懒加载
const ProjectPage = lazy(() => import("@/pages/ProjectPage"));
// ❌ 避免:直接导入大型页面
import ProjectPage from "@/pages/ProjectPage";
```
### 5.2 错误边界
```typescript
// src/app/Router.tsx
import { ErrorBoundary } from '@components/common/ErrorBoundary';
const router = createBrowserRouter([
{
path: '/',
element: ,
errorElement: ,
children: [
// ... 子路由
],
},
]);
```
### 5.3 路由预加载
```typescript
// 鼠标悬停时预加载
import { Link } from 'react-router-dom';
function ProjectCard({ project }: { project: Project }) {
const handleMouseEnter = () => {
// 预加载项目页面
import('@/pages/ProjectPage');
};
return (
{project.name}
);
}
```
---
## 相关文档
- [项目结构](./02-project-structure.md)
- [状态管理](./04-state-management.md)
- [开发规范](./13-dev-standards.md)
---
**最后更新**:2025-01-18 | **版本**:v1.1