-
React 19 + React-Router v7 超级详细实用、好理解的优雅动态路由懒加
- 网站名称:React 19 + React-Router v7 超级详细实用、好理解的优雅动态路由懒加
- 网站分类:技术文章
- 收录时间:2025-09-14 16:09
- 网站地址:
“React 19 + React-Router v7 超级详细实用、好理解的优雅动态路由懒加” 网站介绍
- 本文仅面向前端用户,其他端请绕道。
- 项目选型了 Rspack、React 19、React Router v7 作为项目基础。
- 按 Rspack 官方教程搭建下来,顺利启动项目,并按 React Router v7 官方文档简单集成。
问题
- 集成进来的都很丑,而且做懒加载实现方式不够优雅,而且网上也都是如下图一般的教程。 这个还行,比其他的好多了,但是还不够优雅
其他的都如下图一般,他们写的难道不膈应吗?
过程
- 发现了问题,那么我们就来想办法来解决,给自己先提一个需求
- 1、可配置化
- 2、最多配置一个地方
- 3、支持 middlewares 这里可以喊后端同学看看,这个概念在前端里面可以叫做路由守卫 实现了这个,基本上其他的都很好实现了
- 第一步,我们在 index.tsx 引入 App
import ReactDOM from 'react-dom/client'
import App from './App'
const rootEl = document.getElementById('root')
if (rootEl) {
const root = ReactDOM.createRoot(rootEl)
root.render(<App />)
}
- 第二步,我们在 App.tsx 中引入 RouterProvider
import { ConfigProvider, App as AppContainer } from 'antd'
import zhCN from 'antd/locale/zh_CN'
import './App.less'
import { RouterProvider } from 'react-router'
import { router } from './router'
const App = () => {
return (
<ConfigProvider locale={zhCN}>
<AppContainer component={false}>
<RouterProvider router={router} />
</AppContainer>
</ConfigProvider>
)
}
export default App
- 第三步,我们先实现懒加载组件 components/LazyImport
import { ComponentType, FC, LazyExoticComponent, Suspense } from 'react'
import LazyLoading from '@/components/LazyLoading'
interface LazyImportProps {
lazy?: LazyExoticComponent<ComponentType>
}
export const LazyImport: FC<LazyImportProps> = ({ lazy }) => {
const Component = lazy ? lazy : () => null
return (
<Suspense fallback={<LazyLoading />}>
<Component />
</Suspense>
)
}
- 第四步,我们先实现懒加载 Loading 组件 components/LazyLoading
import { Col, Row, Spin } from 'antd'
const LazyLoading = () => {
return (
<Row align="middle" justify="center" style={{ minHeight: '100%' }}>
<Col>
<Spin spinning />
</Col>
</Row>
)
}
export default LazyLoading
- 第五步,我们来实现下 router/index.tsx这里细心点看,应该可以发现爆改了下 element 属性类型然后导出了个 router 变量给 RouterProvider,主要是为了以后可以在非页面中使用路由能力
import { lazy } from 'react'
import { buildRoutes, RouteConfig } from './utils'
import { createBrowserRouter } from 'react-router'
import ErrorBoundary from '@/components/ErrorBoundary'
const routeConfig: RouteConfig[] = [
{
ErrorBoundary: ErrorBoundary,
children: [
{
path: '/login',
element: lazy(() => import('@/pages/Login')),
},
{
// 应用基础布局
element: lazy(() => import('@/layouts/BasicLayout')),
middlewares: [
// 管理员登录验证中间件
lazy(() => import('@/middlewares/AdminAuthMiddleware')),
],
children: [
{
path: '/',
index: true,
element: lazy(() => import('@/pages/Home')),
},
{
// 谷歌验证
path: '/google-2fa',
element: lazy(() => import('@/pages/Google2FA')),
},
{
middlewares: [
// 谷歌验证中间件
lazy(() => import('@/middlewares/AdminGoogle2FAMiddleware')),
// 页面权限验证中间件
lazy(() => import('@/middlewares/AdminPagePermissionMiddleware')),
],
children: [
{
// 解绑谷歌验证
path: '/unbind-google-2fa',
element: lazy(() => import('@/pages/UnbindGoogle2FA')),
},
{
// 修改密码
path: '/change-password',
element: lazy(() => import('@/pages/ChangePassword')),
},
{
// 仪表盘
path: '/dashboard',
element: lazy(() => import('@/pages/Dashboard')),
},
{
// 系统设置
path: '/setting',
element: lazy(() => import('@/pages/Setting')),
},
{
// 管理员管理
path: '/admin',
element: lazy(() => import('@/pages/Admin')),
},
{
// 角色管理
path: '/admin/role',
element: lazy(() => import('@/pages/AdminRole')),
},
{
// 权限管理
path: '/admin/permission',
element: lazy(() => import('@/pages/AdminPermission')),
},
],
},
],
},
],
},
]
export const routes = buildRoutes(routeConfig)
export const router = createBrowserRouter(routes)
第六步,为了实现我们的第五步功能,我们来实现下 router/utils.tsx
- 重点就是这个文件啦
- 为了更好的实现和IDE智能提示(最讨厌IDE爆红了)
- 我们自定义了一个 RouteConfig 来重新实现路由配置,直接继承自 RouteObject,并且为了配置组件统一性,减除了不必要的属性(lazy,Component,children,element)
- 我们自定义了 element、middlewares、children 属性
import { Outlet, RouteObject } from 'react-router'
import { ComponentType, LazyExoticComponent } from 'react'
import { LazyImport } from '@/components/LazyImport'
export type LazyComponent = LazyExoticComponent<ComponentType>
export type RouteConfig = Omit<
RouteObject,
'element' | 'children' | 'Component' | 'lazy'
> & {
element?: LazyComponent
middlewares?: LazyComponent[]
children?: RouteConfig[]
}
export const buildRoutes = (routes: RouteConfig[]): RouteObject[] => {
return routes.map((item) => {
const { element, middlewares, children, ...restProps } = item
// 要返回的路由对象
let routeObject: RouteObject = {
...restProps,
}
// 递归构建子路由
if (children) {
routeObject.children = buildRoutes(children)
}
// 异步加载组件
routeObject.element = element ? <LazyImport lazy={element} /> : undefined
// 中间件处理
if (middlewares && middlewares.length > 0) {
// 从后往前遍历中间件,这样中间件的执行顺序就是从前往后
// 例如:[A, B, C] => A(B(C()))
for (let i = middlewares.length - 1; i >= 0; i--) {
const middleware = middlewares[i]
routeObject = {
element: <LazyImport lazy={middleware} />,
children: [routeObject],
}
}
} else {
// 如果没有中间件,也没有 element 则传入 <Outlet />
routeObject.element = routeObject.element ?? <Outlet />
}
// 返回路由对象
return routeObject
})
}
- 最终效果
具体可以将项目拉下来体验下,感谢各位的阅读,也欢迎各位评论区留言指点不足之处。
更多相关网站
- 高效使用Java构建工具,Maven篇|云效工程师指北
- CBN丨China's consumer prices hold steady in November
- Token、Session、Cookie、JWT、OAuth2:一文给你彻底讲透!
- 胆小的跳蛛利用天敌蚂蚁作保镖逃离毒蜘蛛追杀
- Spring Boot 私有文件保护:签名 URL + 权限控制 + 限流一体化方案
- Spring Boot 企业级应用与微服务实战指南
- Alibaba Leads $60 Million Series B Round in AI Video Startup AISphere
- 基于 Vue3+Vite+Antd 企业级中后台管理
- Maven 使用说明和配置_maven配置详解
- AI Agents Could Replace Apps Entirely, Says Ant Group CEO
- Shanghai blockchain park proves WAIC's worth
- 数据治理(十二):Ranger2.1.0 源码编译
- CBN丨China pledges expanded market access for foreign investors
- Spring Boot 2.x → 3.x 实战迁移
- vue-antd后台管理系统_vue ant
- Conference on the Bund: young innovators shine as China's next tech generation
- JD.com Drives Robotics Funding Frenzy With Investments in LimX Dynamics, Spirit AI, and EngineAI
- Remarks by H.E. Xi Jinping
- 最近发表
- 标签列表
-
- mydisktest_v298 (35)
- sql 日期比较 (33)
- document.appendchild (35)
- 头像打包下载 (35)
- 梦幻诛仙表情包 (36)
- java面试宝典2019pdf (26)
- disk++ (30)
- 加密与解密第四版pdf (29)
- iteye (26)
- centos7.4下载 (32)
- intouch2014r2sp1永久授权 (33)
- jdk1.8.0_191下载 (27)
- axure9注册码 (30)
- 兔兔工程量计算软件下载 (27)
- ccproxy破解版 (31)
- aida64模板 (28)
- engine=innodb (33)
- shiro jwt (28)
- segoe ui是什么字体 (27)
- head first java电子版 (32)
- clickhouse中文文档 (28)
- jdk-8u181-linux-x64.tar.gz (32)
- 计算机网络自顶向下pdf (34)
- -dfile.encoding=utf-8 (33)
- jdk1.9下载 (32)