路由
本文档详细说明了项目中路由的设计与实现,包括路由文件结构、核心功能、路由守卫、工具函数以及类型定义等内容。
路由文件结构
项目中的路由文件分布如下:
index.tsx
:核心路由配置文件,定义了所有的路由规则。authGuard.tsx
:路由守卫文件,用于处理权限校验。index.ts
:工具函数文件,包含路由相关的辅助函数。lazyLoad.tsx
:封装的懒加载实现,用于优化路由加载性能。routeType.ts
:路由类型定义文件,用于约束路由的结构和元信息。
核心路由配置
核心路由配置位于 index.tsx
,通过 constantRoutes
定义了项目的所有公共路由。
公共路由
公共路由分为以下几类:
重定向路由:
path: '/'
:默认重定向到/home
。
主要页面路由:
/login
:登录页面。/register
:注册页面。/forgetPassword
:忘记密码页面。/home
:首页,带有 TabBar。/example
:示例页面,带有 TabBar。/mine
:我的页面,带有 TabBar,隐藏顶部导航栏。/theme
:主题设置页面。
示例功能路由:
/mock
:Mock 数据演示页面。/echarts
:Echarts 图表演示页面。/icon
:图标示例页面。/keepAlive
:支持 KeepAlive 缓存的页面。
每个路由可以通过 meta
字段定义额外的信息,例如标题、图标、是否显示在 TabBar 中等。
路由示例:
tsx
{
path: '/home',
element: lazyLoad(lazy(() => import('@/views/Home'))),
meta: {
title: '首页',
key: 'Home',
icon: 'HomeO',
iconType: 'react-vant',
tabBar: true,
i18n: 'home',
},
}
路由守卫
路由守卫文件 authGuard.tsx
实现了权限校验逻辑,确保用户访问受限页面时的安全性。
核心逻辑
白名单:定义了无需权限即可访问的路由,例如登录、注册、忘记密码页面。
tsxconst whiteList = ['/login', '/register', '/forgetPassword'];
权限校验:
- 如果用户已登录但尝试访问登录页面,则重定向到首页。
- 如果用户未登录且访问非白名单页面,则重定向到登录页面。
动态设置页面标题:根据路由的
meta.title
动态设置页面标题。
示例代码:
tsx
if (hasToken) {
if (pathname === LOGIN_URL) {
return <Navigate to="/" />;
}
} else {
if (!whiteList.includes(pathname)) {
return <Navigate to="/login" replace />;
}
}
工具函数
工具函数位于 index.ts
文件中,提供了以下功能:
过滤 TabBar 路由
filterTabBar
函数用于过滤出需要显示在 TabBar 上的路由。
tsx
export const filterTabBar = (routers: RouteObjectType[]) => {
const tabBarRouter: RouteObjectType[] = [];
const deep = (routerList: RouteObjectType[]) => {
routerList.forEach((item) => {
if (item.meta?.tabBar) {
tabBarRouter.push(item);
}
if (item.children && item.children.length) {
deep(item.children);
}
});
};
deep(routers);
return tabBarRouter;
};
路由查询
searchRoute
函数用于根据路径查询对应的路由对象。
tsx
export const searchRoute = (path: string, routes: RouteObjectType[] = []): RouteObjectType => {
let result: RouteObjectType = {};
for (const item of routes) {
if (item.path === path) return item;
if (item.children) {
const res = searchRoute(path, item.children);
if (Object.keys(res).length) result = res;
}
}
return result;
};
过滤 KeepAlive 路由
filterKeepAlive
函数用于过滤出需要缓存的路由。
tsx
export const filterKeepAlive = (routers: RouteObjectType[]) => {
const cacheRouter: string[] = [];
const deep = (routerList: RouteObjectType[]) => {
routerList.forEach((item) => {
if (item.meta?.keepAlive && item.path) {
cacheRouter.push(item.path as string);
}
if (item.children && item.children.length) {
deep(item.children);
}
});
};
deep(routers);
return cacheRouter;
};
懒加载实现
懒加载功能由 lazyLoad.tsx
实现,使用 React.Suspense
包裹动态加载的组件,并提供加载中的占位符。
示例代码:
tsx
const lazyLoad = (Component: LazyExoticComponent<any>): ReactNode => {
return (
<Suspense fallback={<Loading type="ball" className="h-full flex-center" />}>
<Component />
</Suspense>
);
};
调用示例:
tsx
element: lazyLoad(lazy(() => import('@/views/Home')));
路由类型定义
路由类型定义位于 routeType.ts
文件中,主要定义了路由对象的结构和元信息。
MetaType
路由元信息
MetaType
定义了路由的元信息字段,例如标题、图标、是否缓存等:
tsx
export interface MetaType {
title: string; // 路由标题
icon?: string; // 菜单图标
iconType?: string; // 图标类型
tabBar?: boolean; // 是否显示在底部导航栏
hiddenNavBar?: boolean; // 是否隐藏顶部导航栏
key?: string; // 路由唯一标识
keepAlive?: boolean; // 是否缓存
i18n?: string; // 国际化 key
}
RouteObjectType
路由对象
RouteObjectType
定义了路由的完整结构,包括路径、组件、子路由等:
tsx
export interface RouteObjectType {
path?: string; // 路由路径
element?: React.ReactNode; // 路由组件
children?: RouteObjectType[]; // 子路由
meta?: MetaType; // 路由元信息
keepAlive?: boolean; // 是否缓存
isLink?: string; // 是否为外部链接
}
总结
本项目的路由设计具有以下特点:
- 模块化:路由配置、守卫、工具函数、类型定义分离,便于维护。
- 动态化:通过
meta
字段实现动态标题、图标等配置。 - 性能优化:支持懒加载和路由缓存(KeepAlive)。
- 安全性:通过路由守卫实现权限控制。
- 类型约束:通过 TypeScript 类型定义,确保路由配置的规范性。