@vlian/router 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,483 @@
1
+ # @vlian/router
2
+
3
+ 基于 React Router 的高级路由管理包,支持动态路由、权限控制、路由转换等功能。
4
+
5
+ ## 📦 安装
6
+
7
+ ```bash
8
+ npm install @vlian/router
9
+ # 或
10
+ pnpm add @vlian/router
11
+ # 或
12
+ yarn add @vlian/router
13
+ ```
14
+
15
+ ## 🔧 依赖要求
16
+
17
+ 本项目需要以下 peer dependencies:
18
+
19
+ - `react`: ^19.2.0
20
+ - `react-dom`: ^19.2.0
21
+ - `react-router-dom`: ^7.0.0
22
+ - `@ant-design/cssinjs`: >=1.24.0
23
+ - `classnames`: >=2.3.0
24
+
25
+ ## ✨ 特性
26
+
27
+ - 🚀 **动态路由加载** - 支持从 API 动态获取路由配置
28
+ - 🔐 **权限控制** - 支持基于角色和登录状态的权限控制
29
+ - 🎨 **布局系统** - 灵活的布局配置,支持嵌套布局
30
+ - ⚡ **懒加载** - 路由组件自动懒加载,优化首屏性能
31
+ - 🔄 **路由转换** - 将自定义路由格式自动转换为 React Router 格式
32
+ - 📱 **子应用支持** - 支持微前端子应用模式
33
+ - 🎯 **类型安全** - 完整的 TypeScript 类型定义
34
+ - 🎭 **加载状态** - 内置加载动画,支持自定义加载组件
35
+ - 🛡️ **错误处理** - 支持自定义错误边界组件
36
+ - 📋 **菜单生成** - 自动从路由配置生成菜单数据
37
+
38
+ ## 📖 使用指南
39
+
40
+ ### 基础用法
41
+
42
+ ```tsx
43
+ import { RouterProvider } from '@vlian/router';
44
+ import type { RouteItem } from '@vlian/router';
45
+
46
+ // 定义路由组件导入映射
47
+ const imports = {
48
+ // 页面组件
49
+ pages: {
50
+ root: () => import('./pages/Root'),
51
+ home: () => import('./pages/Home'),
52
+ about: () => import('./pages/About'),
53
+ '404': () => import('./pages/NotFound'),
54
+ },
55
+ // 布局组件
56
+ layouts: {
57
+ root: () => import('./layouts/RootLayout'),
58
+ admin: () => import('./layouts/AdminLayout'),
59
+ },
60
+ // 加载组件
61
+ loadings: {
62
+ root: () => import('./components/Loading'),
63
+ },
64
+ // 错误组件
65
+ errors: {
66
+ root: () => import('./components/ErrorBoundary'),
67
+ },
68
+ };
69
+
70
+ // 获取动态路由的函数
71
+ const fetchRoutes = async (): Promise<RouteItem[]> => {
72
+ const response = await fetch('/api/routes');
73
+ return response.json();
74
+ };
75
+
76
+ function App() {
77
+ return (
78
+ <RouterProvider
79
+ fetchRoutes={fetchRoutes}
80
+ imports={imports}
81
+ />
82
+ );
83
+ }
84
+ ```
85
+
86
+ ### 路由配置格式
87
+
88
+ 路由配置使用 `RouteItem` 类型,支持以下字段:
89
+
90
+ ```typescript
91
+ type RouteItem = {
92
+ // 布局组件的 key(对应 imports.layouts 中的键)
93
+ layout?: string | null;
94
+
95
+ // 页面组件的 key(对应 imports.pages 中的键)
96
+ page?: string | null;
97
+
98
+ // 加载组件的 key(对应 imports.loadings 中的键)
99
+ loading?: string | null;
100
+
101
+ // 错误组件的 key(对应 imports.errors 中的键)
102
+ errors?: string | null;
103
+
104
+ // 路由名称,唯一标识
105
+ name: string;
106
+
107
+ // 路由路径
108
+ path: string | undefined;
109
+
110
+ // 是否为分组路由(不渲染自身,只作为容器)
111
+ isGroup?: boolean;
112
+
113
+ // 是否启用重定向到第一个子路由
114
+ enableRedirection?: boolean;
115
+
116
+ // 路由元数据
117
+ handle: RouteItemHandle;
118
+
119
+ // 子路由
120
+ children?: RouteItem[];
121
+ };
122
+
123
+ type RouteItemHandle = {
124
+ // 路由标题
125
+ title: string;
126
+
127
+ // 国际化 key
128
+ i18nKey?: string;
129
+
130
+ // 排序顺序
131
+ order: number;
132
+
133
+ // 图标
134
+ icon?: string;
135
+
136
+ // 在菜单中隐藏
137
+ hideInMenu?: boolean;
138
+
139
+ // 隐藏页脚
140
+ hideFooter?: boolean;
141
+
142
+ // 保活(Keep Alive)
143
+ keepAlive?: boolean;
144
+
145
+ // 是否需要登录
146
+ needLogin?: boolean;
147
+
148
+ // 允许访问的角色列表
149
+ roles?: string[];
150
+
151
+ // 其他自定义字段
152
+ [key: string]: unknown;
153
+ };
154
+ ```
155
+
156
+ ### 路由配置示例
157
+
158
+ ```typescript
159
+ const routes: RouteItem[] = [
160
+ {
161
+ name: 'home',
162
+ path: '/home',
163
+ page: 'home',
164
+ layout: 'root',
165
+ handle: {
166
+ title: '首页',
167
+ order: 1,
168
+ icon: 'home',
169
+ needLogin: true,
170
+ },
171
+ },
172
+ {
173
+ name: 'admin',
174
+ path: '/admin',
175
+ layout: 'admin',
176
+ isGroup: true,
177
+ enableRedirection: true,
178
+ handle: {
179
+ title: '管理后台',
180
+ order: 2,
181
+ icon: 'admin',
182
+ roles: ['admin'],
183
+ },
184
+ children: [
185
+ {
186
+ name: 'admin-users',
187
+ path: '/admin/users',
188
+ page: 'adminUsers',
189
+ handle: {
190
+ title: '用户管理',
191
+ order: 1,
192
+ },
193
+ },
194
+ {
195
+ name: 'admin-settings',
196
+ path: '/admin/settings',
197
+ page: 'adminSettings',
198
+ handle: {
199
+ title: '系统设置',
200
+ order: 2,
201
+ },
202
+ },
203
+ ],
204
+ },
205
+ ];
206
+ ```
207
+
208
+ ### 使用路由 Hook
209
+
210
+ ```tsx
211
+ import { useRoute } from '@vlian/router';
212
+
213
+ function MyComponent() {
214
+ const route = useRoute();
215
+
216
+ // route 包含以下信息:
217
+ // - id: 路由 ID
218
+ // - pathname: 当前路径
219
+ // - search: 查询字符串
220
+ // - hash: 哈希值
221
+ // - query: 解析后的查询参数对象
222
+ // - fullPath: 完整路径(pathname + search + hash)
223
+ // - handle: 路由元数据
224
+ // - data: 路由数据(来自 loader)
225
+
226
+ return (
227
+ <div>
228
+ <h1>{route.handle?.title}</h1>
229
+ <p>当前路径: {route.pathname}</p>
230
+ <p>查询参数: {JSON.stringify(route.query)}</p>
231
+ </div>
232
+ );
233
+ }
234
+ ```
235
+
236
+ ### 使用导航工具
237
+
238
+ 在子应用模式下,可以通过 `window.$router` 访问导航工具:
239
+
240
+ ```typescript
241
+ // 导航到指定路径
242
+ window.$router.push('/home');
243
+
244
+ // 带查询参数导航
245
+ window.$router.push('/users', { page: 1, size: 10 });
246
+
247
+ // 替换当前历史记录
248
+ window.$router.replace('/login');
249
+
250
+ // 返回上一页
251
+ window.$router.back();
252
+
253
+ // 前进
254
+ window.$router.forward();
255
+
256
+ // 跳转到首页
257
+ window.$router.goHome();
258
+
259
+ // 向上导航(父路由)
260
+ window.$router.navigateUp();
261
+
262
+ // 重新加载
263
+ window.$router.reload();
264
+
265
+ // 使用 React Router 的 navigate 方法
266
+ window.$router.navigate('/path', { replace: true });
267
+ ```
268
+
269
+ ### 生成菜单数据
270
+
271
+ ```tsx
272
+ import { formatMenusDate } from '@vlian/router';
273
+ import { useRoute } from '@vlian/router';
274
+
275
+ function Menu() {
276
+ const route = useRoute();
277
+ // 假设你有路由数据
278
+ const routes = route.dynamicRoutes || [];
279
+ const menus = formatMenusDate(routes);
280
+
281
+ return (
282
+ <ul>
283
+ {menus.map(menu => (
284
+ <li key={menu.key}>
285
+ <a href={menu.path}>{menu.name}</a>
286
+ {menu.children && (
287
+ <ul>
288
+ {menu.children.map(subMenu => (
289
+ <li key={subMenu.key}>
290
+ <a href={subMenu.path}>{subMenu.name}</a>
291
+ </li>
292
+ ))}
293
+ </ul>
294
+ )}
295
+ </li>
296
+ ))}
297
+ </ul>
298
+ );
299
+ }
300
+ ```
301
+
302
+ ### RouterProvider 配置选项
303
+
304
+ ```tsx
305
+ <RouterProvider
306
+ // 必需:获取动态路由的函数
307
+ fetchRoutes={fetchRoutes}
308
+
309
+ // 必需:组件导入映射
310
+ imports={imports}
311
+
312
+ // 可选:根路由配置(默认使用内置配置)
313
+ rootRoutes={customRootRoutes}
314
+
315
+ // 可选:静态路由(默认包含 404 路由)
316
+ staticRoutes={customStaticRoutes}
317
+
318
+ // 可选:React Router 配置选项
319
+ options={{
320
+ future: {
321
+ v7_startTransition: true,
322
+ v7_relativeSplatPath: true,
323
+ },
324
+ }}
325
+
326
+ // 可选:是否为子应用模式(默认 false)
327
+ isSubApp={false}
328
+
329
+ // 可选:自定义加载组件
330
+ loadingRender={<CustomLoading />}
331
+
332
+ // 可选:加载动画大小(默认 '24px')
333
+ loadingSize="32px"
334
+
335
+ // 可选:加载动画颜色(默认 'currentColor')
336
+ loadingColor="#1890ff"
337
+
338
+ // 可选:加载动画透明度(默认 0.25)
339
+ loadingOpacity={0.3}
340
+ />
341
+ ```
342
+
343
+ ## 🎨 组件导出
344
+
345
+ ### RouterProvider
346
+
347
+ 路由提供者组件,用于初始化和管理路由系统。
348
+
349
+ ### Hooks
350
+
351
+ - `useRoute<T>()` - 获取当前路由信息
352
+ - `useRouterTransform()` - 路由转换 Hook(内部使用)
353
+
354
+ ### 工具函数
355
+
356
+ - `navigator(router)` - 创建导航工具对象
357
+ - `formatMenusDate(routes)` - 将路由配置格式化为菜单数据
358
+
359
+ ## 🔍 类型定义
360
+
361
+ 主要类型定义:
362
+
363
+ - `RouteItem` - 路由项类型
364
+ - `RouteItemHandle` - 路由元数据类型
365
+ - `RouteMapType` - 路由组件映射类型
366
+ - `RouterProviderProps` - RouterProvider 属性类型
367
+ - `RouterContextType` - 路由上下文类型
368
+ - `FormattedMenuItem` - 格式化后的菜单项类型
369
+
370
+ ## 🚀 高级用法
371
+
372
+ ### 自定义根路由
373
+
374
+ ```typescript
375
+ import { RouteItem } from '@vlian/router';
376
+
377
+ const customRootRoutes: RouteItem = {
378
+ name: 'root',
379
+ path: '/',
380
+ page: 'root',
381
+ layout: 'customRoot',
382
+ handle: {
383
+ title: '应用根',
384
+ order: 0,
385
+ },
386
+ children: [],
387
+ };
388
+
389
+ <RouterProvider
390
+ fetchRoutes={fetchRoutes}
391
+ imports={imports}
392
+ rootRoutes={customRootRoutes}
393
+ />
394
+ ```
395
+
396
+ ### 自定义静态路由
397
+
398
+ ```typescript
399
+ import { RouteItem } from '@vlian/router';
400
+
401
+ const customStaticRoutes: RouteItem[] = [
402
+ {
403
+ name: '403',
404
+ path: '/403',
405
+ page: 'forbidden',
406
+ handle: {
407
+ title: '无权限',
408
+ order: 99999997,
409
+ },
410
+ },
411
+ {
412
+ name: '404',
413
+ path: '/404',
414
+ page: 'notFound',
415
+ handle: {
416
+ title: '页面不存在',
417
+ order: 99999998,
418
+ },
419
+ },
420
+ {
421
+ name: 'notFound',
422
+ path: '*',
423
+ page: 'notFound',
424
+ handle: {
425
+ title: '页面不存在',
426
+ order: 99999999,
427
+ },
428
+ },
429
+ ];
430
+
431
+ <RouterProvider
432
+ fetchRoutes={fetchRoutes}
433
+ imports={imports}
434
+ staticRoutes={customStaticRoutes}
435
+ />
436
+ ```
437
+
438
+ ### 子应用模式
439
+
440
+ 在微前端场景中,可以启用子应用模式,通过 `window.$router` 访问路由导航:
441
+
442
+ ```tsx
443
+ <RouterProvider
444
+ fetchRoutes={fetchRoutes}
445
+ imports={imports}
446
+ isSubApp={true}
447
+ />
448
+ ```
449
+
450
+ ## 📝 注意事项
451
+
452
+ 1. **路由名称唯一性**:每个路由的 `name` 字段必须唯一,它作为路由的唯一标识符。
453
+
454
+ 2. **组件导出格式**:所有通过 `imports` 导入的组件必须使用默认导出,例如:
455
+ ```typescript
456
+ // ✅ 正确
457
+ export default function MyPage() { ... }
458
+
459
+ // ❌ 错误
460
+ export function MyPage() { ... }
461
+ ```
462
+
463
+ 3. **布局和页面**:
464
+ - 如果路由有 `layout` 且不是分组路由,会使用布局组件包裹页面
465
+ - 如果路由有 `page` 且有子路由,会自动创建 index 路由来渲染页面
466
+ - 分组路由(`isGroup: true`)不会渲染自身,只作为子路由的容器
467
+
468
+ 4. **路由排序**:子路由会根据 `handle.order` 自动排序,数值越小越靠前。
469
+
470
+ 5. **权限控制**:当前版本的路由转换支持权限相关的元数据配置,但具体的权限验证逻辑需要在业务层面实现。
471
+
472
+ ## 🤝 贡献
473
+
474
+ 欢迎提交 Issue 和 Pull Request!
475
+
476
+ ## 📄 许可证
477
+
478
+ MIT
479
+
480
+ ## 🔗 相关链接
481
+
482
+ - [React Router 文档](https://reactrouter.com/)
483
+ - [React 文档](https://react.dev/)
@@ -1 +1 @@
1
- {"version":3,"file":"square-rotate.d.ts","sourceRoot":"","sources":["../../src/styles/square-rotate.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,sBAAsB;;;;CAiBlC,CAAC"}
1
+ {"version":3,"file":"square-rotate.d.ts","sourceRoot":"","sources":["../../src/styles/square-rotate.ts"],"names":[],"mappings":"AAyCA,eAAO,MAAM,sBAAsB;;;;CAiBlC,CAAC"}
@@ -1,5 +1,4 @@
1
- import Keyframes from '@ant-design/cssinjs/lib/Keyframes';
2
- import { useStyleRegister } from '@ant-design/cssinjs';
1
+ import { Keyframes, useStyleRegister } from '@ant-design/cssinjs';
3
2
  // 定义动画
4
3
  var squareRotate2Animation = new Keyframes('square-rotate-2-animation', {
5
4
  '0%': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vlian/router",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "基于 React Router 的路由管理包,支持动态路由、权限控制、路由转换等功能",
5
5
  "keywords": [
6
6
  "router",