@zphhpzzph/vue-route-gen 1.1.0 → 2.0.0
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 +459 -9
- package/dist/cli.js +0 -0
- package/dist/extract-meta.d.ts +27 -11
- package/dist/extract-meta.d.ts.map +1 -1
- package/dist/extract-meta.js +105 -16
- package/dist/extract-meta.js.map +1 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +215 -25
- package/dist/index.js.map +1 -1
- package/dist/vite.d.ts +51 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +242 -0
- package/dist/vite.js.map +1 -0
- package/package.json +7 -5
- package/dist/runtime/index.d.ts +0 -49
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -28
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/types.d.ts +0 -16
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/types.js +0 -5
- package/dist/runtime/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ Vue 3 基于文件系统的路由生成器,为 Vue Router 提供完整的类
|
|
|
13
13
|
- TypeScript 支持并生成完整类型
|
|
14
14
|
- **类型安全的路由 Hooks**(`useRoute` 和 `useRouter` 提供完整类型推断)
|
|
15
15
|
- **自动从动态路由提取参数类型**
|
|
16
|
+
- **`<route>` 自定义块支持** - 在 SFC 中定义路由元数据,零运行时开销
|
|
17
|
+
- **精确的字面量类型推断** - 为路由元数据提供编译时类型安全,详见 [字面量类型推断文档](./docs/LiteralTypes.md)
|
|
16
18
|
|
|
17
19
|
## 安装
|
|
18
20
|
|
|
@@ -63,7 +65,71 @@ src/pages/
|
|
|
63
65
|
|
|
64
66
|
## 配置选项
|
|
65
67
|
|
|
66
|
-
###
|
|
68
|
+
### Vite 配置
|
|
69
|
+
|
|
70
|
+
`@zphhpzzph/vue-route-gen` 提供了两个 Vite 插件:
|
|
71
|
+
|
|
72
|
+
#### 1. `routeBlockPlugin()` - 处理路由自定义块(必需)
|
|
73
|
+
|
|
74
|
+
必须添加,用于移除 `<route>` 自定义块和 `defineRoute()` 宏:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// vite.config.ts
|
|
78
|
+
import { defineConfig } from 'vite';
|
|
79
|
+
import vue from '@vitejs/plugin-vue';
|
|
80
|
+
import { routeBlockPlugin } from '@zphhpzzph/vue-route-gen/vite';
|
|
81
|
+
|
|
82
|
+
export default defineConfig({
|
|
83
|
+
plugins: [
|
|
84
|
+
routeBlockPlugin(), // 处理 <route> 自定义块和 defineRoute()
|
|
85
|
+
vue(),
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**注意**:`routeBlockPlugin` 会移除 `<route>` 自定义块,因为这些块已经在构建时被 `vue-route-gen` 提取并合并到路由配置中,不需要在运行时处理。
|
|
91
|
+
|
|
92
|
+
#### 2. `routeGenPlugin()` - 自动生成路由(推荐)
|
|
93
|
+
|
|
94
|
+
**开发体验优化**:自动监听文件变化并重新生成路由,无需手动运行命令。
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// vite.config.ts
|
|
98
|
+
import { defineConfig } from 'vite';
|
|
99
|
+
import vue from '@vitejs/plugin-vue';
|
|
100
|
+
import { routeBlockPlugin, routeGenPlugin } from '@zphhpzzph/vue-route-gen/vite';
|
|
101
|
+
|
|
102
|
+
export default defineConfig({
|
|
103
|
+
plugins: [
|
|
104
|
+
routeBlockPlugin(), // 1. 最先执行
|
|
105
|
+
routeGenPlugin(), // 2. 自动生成路由
|
|
106
|
+
vue(), // 3. Vue 插件
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**功能特性**:
|
|
112
|
+
|
|
113
|
+
- ✅ 开发服务器启动时自动生成路由
|
|
114
|
+
- ✅ 监听 `pages` 目录的文件变化
|
|
115
|
+
- ✅ 智能判断是否需要重新生成(避免不必要的重建)
|
|
116
|
+
- ✅ 自动触发 HMR 更新
|
|
117
|
+
- ✅ 支持自定义配置
|
|
118
|
+
|
|
119
|
+
**自定义配置**:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
routeGenPlugin({
|
|
123
|
+
pagesDir: './src/pages', // 可选,默认 'src/pages'
|
|
124
|
+
outFile: './src/router/route.gen.ts', // 可选,默认 'src/router/route.gen.ts'
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**插件顺序**:`routeBlockPlugin()` → `routeGenPlugin()` → `vue()`
|
|
129
|
+
|
|
130
|
+
详细文档:[Vite 插件使用指南](./docs/VitePlugin.md)
|
|
131
|
+
|
|
132
|
+
### 生成器选项
|
|
67
133
|
|
|
68
134
|
- `pagesDir`: 页面目录路径(默认:`src/pages`)
|
|
69
135
|
- `outFile`: 输出文件路径(默认:`src/router/route.gen.ts`)
|
|
@@ -87,9 +153,306 @@ src/pages/
|
|
|
87
153
|
3. `ROUTE_PATH_BY_NAME` - 按名称查找路径
|
|
88
154
|
4. `RouteParams` - 每个路由的参数类型接口
|
|
89
155
|
5. `RouteParamsByName<T>` - 根据路由名称获取参数类型的工具类型
|
|
90
|
-
6. `
|
|
91
|
-
7. `
|
|
92
|
-
8. `
|
|
156
|
+
6. `RouteMetaMap` - 每个路由的元数据类型接口(从 `<route>` 块提取)
|
|
157
|
+
7. `RouteMetaByName<T>` - 根据路由名称获取元数据类型的工具类型
|
|
158
|
+
8. `routes` - Vue Router 路由记录数组
|
|
159
|
+
9. `useRoute()` - 类型安全的路由访问 Hook,提供参数和元数据类型推断
|
|
160
|
+
10. `useRouter()` - 类型安全的路由导航 Hook,提供参数验证
|
|
161
|
+
|
|
162
|
+
## 使用 `<route>` 自定义块
|
|
163
|
+
|
|
164
|
+
`@zphhpzzph/vue-route-gen` 支持在 Vue SFC 文件中使用 `<route>` 自定义块来定义路由元数据。这些元数据会在**构建时**被提取并合并到生成的路由配置中,**零运行时开销**。
|
|
165
|
+
|
|
166
|
+
### 基础用法
|
|
167
|
+
|
|
168
|
+
在 Vue 组件中添加 `<route>` 自定义块:
|
|
169
|
+
|
|
170
|
+
```vue
|
|
171
|
+
<template>
|
|
172
|
+
<div>
|
|
173
|
+
<h1>用户列表</h1>
|
|
174
|
+
</div>
|
|
175
|
+
</template>
|
|
176
|
+
|
|
177
|
+
<script setup lang="ts">
|
|
178
|
+
// 组件逻辑
|
|
179
|
+
</script>
|
|
180
|
+
|
|
181
|
+
<route>
|
|
182
|
+
{
|
|
183
|
+
"title": "用户列表",
|
|
184
|
+
"layout": "admin",
|
|
185
|
+
"requiresAuth": true,
|
|
186
|
+
"roles": ["admin", "moderator"]
|
|
187
|
+
}
|
|
188
|
+
</route>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 支持的元数据属性
|
|
192
|
+
|
|
193
|
+
| 属性 | 类型 | 说明 |
|
|
194
|
+
|------|------|------|
|
|
195
|
+
| `title` | `string` | 页面标题,用于 document.title 和面包屑 |
|
|
196
|
+
| `layout` | `string \| false` | 布局组件名称,或 `false` 禁用布局 |
|
|
197
|
+
| `keepAlive` | `boolean` | 是否缓存页面组件 |
|
|
198
|
+
| `requiresAuth` | `boolean` | 是否需要认证 |
|
|
199
|
+
| `roles` | `string[]` | 允许访问的用户角色 |
|
|
200
|
+
| `redirect` | `string \| { name: string }` | 重定向配置 |
|
|
201
|
+
| `icon` | `string` | 菜单图标(自定义属性) |
|
|
202
|
+
| `hidden` | `boolean` | 是否隐藏菜单(自定义属性) |
|
|
203
|
+
| `*` | `any` | 支持任何自定义属性 |
|
|
204
|
+
|
|
205
|
+
### JSON 和 JavaScript 对象语法
|
|
206
|
+
|
|
207
|
+
`<route>` 块支持两种语法:
|
|
208
|
+
|
|
209
|
+
#### 1. JSON 语法(推荐)
|
|
210
|
+
|
|
211
|
+
```vue
|
|
212
|
+
<route>
|
|
213
|
+
{
|
|
214
|
+
"title": "用户详情",
|
|
215
|
+
"layout": "admin",
|
|
216
|
+
"requiresAuth": true,
|
|
217
|
+
"roles": ["admin"]
|
|
218
|
+
}
|
|
219
|
+
</route>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### 2. JavaScript 对象语法
|
|
223
|
+
|
|
224
|
+
```vue
|
|
225
|
+
<route>
|
|
226
|
+
{
|
|
227
|
+
title: '用户详情',
|
|
228
|
+
layout: 'admin',
|
|
229
|
+
requiresAuth: true,
|
|
230
|
+
roles: ['admin', 'moderator']
|
|
231
|
+
}
|
|
232
|
+
</route>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### 完整示例
|
|
236
|
+
|
|
237
|
+
#### 用户列表页面
|
|
238
|
+
|
|
239
|
+
```vue
|
|
240
|
+
<!-- src/pages/users/index.vue -->
|
|
241
|
+
<template>
|
|
242
|
+
<div class="users-page">
|
|
243
|
+
<h1>用户列表</h1>
|
|
244
|
+
<UserList />
|
|
245
|
+
</div>
|
|
246
|
+
</template>
|
|
247
|
+
|
|
248
|
+
<script setup lang="ts">
|
|
249
|
+
import UserList from './components/UserList.vue';
|
|
250
|
+
</script>
|
|
251
|
+
|
|
252
|
+
<route>
|
|
253
|
+
{
|
|
254
|
+
"title": "用户列表",
|
|
255
|
+
"layout": "admin",
|
|
256
|
+
"requiresAuth": true,
|
|
257
|
+
"roles": ["admin"],
|
|
258
|
+
"icon": "User",
|
|
259
|
+
"keepAlive": true
|
|
260
|
+
}
|
|
261
|
+
</route>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### 用户详情页面
|
|
265
|
+
|
|
266
|
+
```vue
|
|
267
|
+
<!-- src/pages/users/[id].vue -->
|
|
268
|
+
<template>
|
|
269
|
+
<div class="user-detail">
|
|
270
|
+
<h1>用户详情</h1>
|
|
271
|
+
<UserInfo :user-id="userId" />
|
|
272
|
+
</div>
|
|
273
|
+
</template>
|
|
274
|
+
|
|
275
|
+
<script setup lang="ts">
|
|
276
|
+
import { computed } from 'vue';
|
|
277
|
+
import { useRoute } from '@/router/route.gen';
|
|
278
|
+
import UserInfo from './components/UserInfo.vue';
|
|
279
|
+
|
|
280
|
+
const route = useRoute<'users-[id]>();
|
|
281
|
+
const userId = computed(() => route.params.id);
|
|
282
|
+
</script>
|
|
283
|
+
|
|
284
|
+
<route>
|
|
285
|
+
{
|
|
286
|
+
"title": "用户详情",
|
|
287
|
+
"layout": "admin",
|
|
288
|
+
"requiresAuth": true,
|
|
289
|
+
"roles": ["admin", "moderator"],
|
|
290
|
+
"icon": "UserProfile"
|
|
291
|
+
}
|
|
292
|
+
</route>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### 公开页面(无需认证)
|
|
296
|
+
|
|
297
|
+
```vue
|
|
298
|
+
<!-- src/pages/about.vue -->
|
|
299
|
+
<template>
|
|
300
|
+
<div class="about-page">
|
|
301
|
+
<h1>关于我们</h1>
|
|
302
|
+
<p>这是关于页面</p>
|
|
303
|
+
</div>
|
|
304
|
+
</template>
|
|
305
|
+
|
|
306
|
+
<script setup lang="ts">
|
|
307
|
+
// 组件逻辑
|
|
308
|
+
</script>
|
|
309
|
+
|
|
310
|
+
<route>
|
|
311
|
+
{
|
|
312
|
+
"title": "关于我们",
|
|
313
|
+
"layout": "default",
|
|
314
|
+
"requiresAuth": false,
|
|
315
|
+
"keepAlive": false
|
|
316
|
+
}
|
|
317
|
+
</route>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 自定义元数据属性
|
|
321
|
+
|
|
322
|
+
你可以在 `<route>` 块中添加任何自定义属性,并通过 TypeScript 模块扩展来获得类型支持:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// types/route-meta.d.ts
|
|
326
|
+
declare module '@zphhpzzph/vue-route-gen/runtime' {
|
|
327
|
+
interface RouteMeta {
|
|
328
|
+
icon?: string;
|
|
329
|
+
hidden?: boolean;
|
|
330
|
+
order?: number;
|
|
331
|
+
badge?: string | number;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
然后在组件中使用:
|
|
337
|
+
|
|
338
|
+
```vue
|
|
339
|
+
<route>
|
|
340
|
+
{
|
|
341
|
+
"title": "仪表盘",
|
|
342
|
+
"icon": "Dashboard",
|
|
343
|
+
"hidden": false,
|
|
344
|
+
"order": 1,
|
|
345
|
+
"badge": "New"
|
|
346
|
+
}
|
|
347
|
+
</route>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 构建时提取
|
|
351
|
+
|
|
352
|
+
路由元数据在构建时被提取,零运行时开销:
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
// 生成的 route.gen.ts
|
|
356
|
+
export const routes = [
|
|
357
|
+
{
|
|
358
|
+
path: "/users/:id",
|
|
359
|
+
name: "users-[id]",
|
|
360
|
+
component: () => import("../pages/users/[id].vue"),
|
|
361
|
+
meta: {
|
|
362
|
+
title: "用户详情",
|
|
363
|
+
layout: "admin",
|
|
364
|
+
requiresAuth: true,
|
|
365
|
+
roles: ["admin", "moderator"],
|
|
366
|
+
icon: "UserProfile"
|
|
367
|
+
},
|
|
368
|
+
children: [],
|
|
369
|
+
}
|
|
370
|
+
] satisfies RouteRecordRaw[];
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### 在路由守卫中使用元数据
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// router/guards.ts
|
|
377
|
+
import { router } from './router';
|
|
378
|
+
|
|
379
|
+
router.beforeEach((to, from, next) => {
|
|
380
|
+
const meta = to.meta;
|
|
381
|
+
|
|
382
|
+
// 检查认证
|
|
383
|
+
if (meta.requiresAuth && !isAuthenticated()) {
|
|
384
|
+
return next({ name: 'login' });
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// 检查角色权限
|
|
388
|
+
if (meta.roles && !hasRole(meta.roles)) {
|
|
389
|
+
return next({ name: 'forbidden' });
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 设置页面标题
|
|
393
|
+
if (meta.title) {
|
|
394
|
+
document.title = `${meta.title} - My App`;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
next();
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### 与导航菜单结合
|
|
402
|
+
|
|
403
|
+
```vue
|
|
404
|
+
<!-- components/Sidebar.vue -->
|
|
405
|
+
<script setup lang="ts">
|
|
406
|
+
import { routes } from '@/router/route.gen';
|
|
407
|
+
|
|
408
|
+
const menuItems = routes
|
|
409
|
+
.filter(route => route.meta && !route.meta.hidden)
|
|
410
|
+
.map(route => ({
|
|
411
|
+
title: route.meta?.title,
|
|
412
|
+
icon: route.meta?.icon,
|
|
413
|
+
path: route.path,
|
|
414
|
+
order: route.meta?.order ?? 999,
|
|
415
|
+
}))
|
|
416
|
+
.sort((a, b) => a.order - b.order);
|
|
417
|
+
</script>
|
|
418
|
+
|
|
419
|
+
<template>
|
|
420
|
+
<nav>
|
|
421
|
+
<router-link
|
|
422
|
+
v-for="item in menuItems"
|
|
423
|
+
:key="item.path"
|
|
424
|
+
:to="item.path"
|
|
425
|
+
>
|
|
426
|
+
<Icon :name="item.icon" />
|
|
427
|
+
{{ item.title }}
|
|
428
|
+
</router-link>
|
|
429
|
+
</nav>
|
|
430
|
+
</template>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### 类型安全扩展
|
|
434
|
+
|
|
435
|
+
通过 TypeScript 模块扩展,让你的自定义元数据属性类型安全:
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
// types/route-meta.d.ts
|
|
439
|
+
import '@zphhpzzph/vue-route-gen/runtime';
|
|
440
|
+
|
|
441
|
+
declare module '@zphhpzzph/vue-route-gen/runtime' {
|
|
442
|
+
interface RouteMeta {
|
|
443
|
+
// 页面权限
|
|
444
|
+
permissions?: string[];
|
|
445
|
+
// 页面描述
|
|
446
|
+
description?: string;
|
|
447
|
+
// SEO 关键词
|
|
448
|
+
keywords?: string[];
|
|
449
|
+
// 是否在标签页中打开
|
|
450
|
+
openInTab?: boolean;
|
|
451
|
+
// 自定义中间件
|
|
452
|
+
middleware?: string[];
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
93
456
|
|
|
94
457
|
## 类型安全的路由
|
|
95
458
|
|
|
@@ -100,7 +463,7 @@ src/pages/
|
|
|
100
463
|
```typescript
|
|
101
464
|
// 在 route.gen.ts 中生成
|
|
102
465
|
export interface RouteParams {
|
|
103
|
-
'users-id': {
|
|
466
|
+
'users-[id]': {
|
|
104
467
|
id: string;
|
|
105
468
|
};
|
|
106
469
|
// ... 其他路由
|
|
@@ -109,19 +472,49 @@ export interface RouteParams {
|
|
|
109
472
|
|
|
110
473
|
### 使用 useRoute
|
|
111
474
|
|
|
112
|
-
生成的 `useRoute` Hook
|
|
475
|
+
生成的 `useRoute` Hook 为路由参数和元数据提供完整的类型推断:
|
|
113
476
|
|
|
114
477
|
```typescript
|
|
115
478
|
import { useRoute, ROUTE_NAME } from '@/router/route.gen';
|
|
116
479
|
|
|
117
|
-
const route = useRoute
|
|
118
|
-
// route.params.id 的类型为 `string`
|
|
480
|
+
const route = useRoute();
|
|
119
481
|
|
|
482
|
+
// 类型安全的参数访问
|
|
120
483
|
if (route.name === ROUTE_NAME.USERS_ID) {
|
|
121
|
-
console.log(route.params.id); //
|
|
484
|
+
console.log(route.params.id); // 类型为 string ✅
|
|
485
|
+
|
|
486
|
+
// 类型安全的元数据访问
|
|
487
|
+
console.log(route.meta.title); // 类型为 string ✅
|
|
488
|
+
console.log(route.meta.layout); // 类型为 string ✅
|
|
489
|
+
console.log(route.meta.requiresAuth); // 类型为 boolean ✅
|
|
490
|
+
console.log(route.meta.roles); // 类型为 string[] ✅
|
|
491
|
+
|
|
492
|
+
// ❌ TypeScript 报错:属性不存在
|
|
493
|
+
// console.log(route.meta.wrongProp);
|
|
122
494
|
}
|
|
123
495
|
```
|
|
124
496
|
|
|
497
|
+
**Meta 类型自动推导**:
|
|
498
|
+
- 从 `<route>` 块中提取的元数据会自动生成对应的 TypeScript 类型
|
|
499
|
+
- 不同路由有不同的 meta 类型
|
|
500
|
+
- 访问不存在的 meta 属性时 TypeScript 会报错
|
|
501
|
+
|
|
502
|
+
**获取特定路由的 Meta 类型**:
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
import type { RouteMetaByName } from '@/router/route.gen';
|
|
506
|
+
|
|
507
|
+
// 获取特定路由的 meta 类型
|
|
508
|
+
type UsersIdMeta = RouteMetaByName<typeof ROUTE_NAME.USERS_ID>;
|
|
509
|
+
// 类型为:
|
|
510
|
+
// {
|
|
511
|
+
// title: string;
|
|
512
|
+
// layout: string;
|
|
513
|
+
// requiresAuth: true;
|
|
514
|
+
// roles: string[];
|
|
515
|
+
// } & RouteMeta
|
|
516
|
+
```
|
|
517
|
+
|
|
125
518
|
### 使用 useRouter
|
|
126
519
|
|
|
127
520
|
生成的 `useRouter` Hook 提供类型安全的导航:
|
|
@@ -216,6 +609,54 @@ function navigateToUser(userId: string) {
|
|
|
216
609
|
|
|
217
610
|
## 高级用法
|
|
218
611
|
|
|
612
|
+
### 类型工具(从 `@zphhpzzph/vue-route-gen` 导入)
|
|
613
|
+
|
|
614
|
+
包中提供了一些高级类型工具用于自定义类型安全的路由 hooks:
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
import {
|
|
618
|
+
createTypedUseRoute,
|
|
619
|
+
createTypedUseRouter,
|
|
620
|
+
type TypedRoute,
|
|
621
|
+
type TypedRouter,
|
|
622
|
+
type TypedRouteLocation,
|
|
623
|
+
} from '@zphhpzzph/vue-route-gen';
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
#### 创建自定义类型安全的 useRoute Hook
|
|
627
|
+
|
|
628
|
+
如果需要为特定路由创建类型更精确的 hook:
|
|
629
|
+
|
|
630
|
+
```typescript
|
|
631
|
+
import { createTypedUseRoute } from '@zphhpzzph/vue-route-gen';
|
|
632
|
+
|
|
633
|
+
// 创建针对特定路由的 hook
|
|
634
|
+
const useUserDetailRoute = createTypedUseRoute<'users-[id]', { id: string }>();
|
|
635
|
+
|
|
636
|
+
// 在组件中使用
|
|
637
|
+
const route = useUserDetailRoute();
|
|
638
|
+
console.log(route.params.id); // 类型为 string
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
#### 创建类型安全的 Router
|
|
642
|
+
|
|
643
|
+
```typescript
|
|
644
|
+
import { createTypedUseRouter } from '@zphhpzzph/vue-route-gen';
|
|
645
|
+
|
|
646
|
+
const useRouter = createTypedUseRouter();
|
|
647
|
+
const router = useRouter();
|
|
648
|
+
|
|
649
|
+
// 导航时提供类型检查
|
|
650
|
+
router.push({
|
|
651
|
+
name: 'users-[id]',
|
|
652
|
+
params: { id: '123' },
|
|
653
|
+
});
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
**注意**:大多数情况下,你应该使用生成的 `useRoute()` 和 `useRouter()` hooks(从 `route.gen.ts` 导入),它们已经提供了完整的类型安全。这些底层类型工具主要用于高级自定义场景。
|
|
657
|
+
|
|
658
|
+
> 💡 **深入阅读**:更多高级用法和完整文档,请参阅[文档索引](./docs/README.md)
|
|
659
|
+
|
|
219
660
|
### 获取特定路由的参数类型
|
|
220
661
|
|
|
221
662
|
```typescript
|
|
@@ -248,6 +689,15 @@ src/pages/
|
|
|
248
689
|
1. **始终使用生成的常量**:使用 `ROUTE_NAME` 而不是硬编码字符串
|
|
249
690
|
2. **利用类型推断**:让 TypeScript 为你检查路由参数
|
|
250
691
|
3. **组合使用 Hooks**:`useRoute` 和 `useRouter` 提供完整的类型安全
|
|
692
|
+
4. **使用 `<route>` 块定义元数据**:在组件中直接定义路由元数据,便于维护
|
|
693
|
+
|
|
694
|
+
## 📚 文档
|
|
695
|
+
|
|
696
|
+
查看完整文档:
|
|
697
|
+
- **[文档索引](./docs/README.md)** - 所有文档���导航目录
|
|
698
|
+
- **[更新日志](./CHANGELOG.md)** - 版本更新记录和迁移指南
|
|
699
|
+
- **[路由元数据字面量类型推断](./docs/LiteralTypes.md)** - 精确的类型推断系统详解
|
|
700
|
+
- **[Vite 插件使用指南](./docs/VitePlugin.md)** - 自动路由生成和智能更新
|
|
251
701
|
|
|
252
702
|
## 发布新版本(维护者)
|
|
253
703
|
|
package/dist/cli.js
CHANGED
|
File without changes
|
package/dist/extract-meta.d.ts
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import type { RouteRecordRaw, RouteRecordRedirectOption, _RouteRecordProps } from 'vue-router';
|
|
2
|
+
type RouteRecordProps = _RouteRecordProps;
|
|
3
|
+
/**
|
|
4
|
+
* Route configuration override interface
|
|
5
|
+
* Supports all RouteRecordRaw fields for complete customization
|
|
6
|
+
*/
|
|
7
|
+
export interface RouteConfigOverride {
|
|
8
|
+
path?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
alias?: string | string[];
|
|
11
|
+
redirect?: RouteRecordRedirectOption;
|
|
12
|
+
props?: RouteRecordProps;
|
|
13
|
+
meta?: Record<string, any>;
|
|
14
|
+
children?: RouteRecordRaw[];
|
|
15
|
+
beforeEnter?: any;
|
|
11
16
|
[key: string]: any;
|
|
12
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse Vue SFC and extract complete route configuration
|
|
20
|
+
* Supports both <route> custom block and defineRoute() macro
|
|
21
|
+
*
|
|
22
|
+
* @param filePath - Path to the Vue SFC file
|
|
23
|
+
* @returns Route configuration override, or undefined if no custom config
|
|
24
|
+
* @throws Error if both <route> block and defineRoute() are present
|
|
25
|
+
*/
|
|
26
|
+
export declare function extractRouteConfig(filePath: string): RouteConfigOverride | undefined;
|
|
13
27
|
/**
|
|
14
28
|
* Parse Vue SFC and extract metadata from <route> custom block
|
|
29
|
+
* @deprecated Use extractRouteConfig() instead for full configuration support
|
|
15
30
|
*/
|
|
16
|
-
export declare function extractRouteMeta(filePath: string):
|
|
31
|
+
export declare function extractRouteMeta(filePath: string): Record<string, any>;
|
|
32
|
+
export {};
|
|
17
33
|
//# sourceMappingURL=extract-meta.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-meta.d.ts","sourceRoot":"","sources":["../src/extract-meta.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extract-meta.d.ts","sourceRoot":"","sources":["../src/extract-meta.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/F,KAAK,gBAAgB,GAAG,iBAAiB,CAAC;AAE1C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAiDpF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAStE"}
|