@esmx/router-vue 3.0.0-rc.103

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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +570 -0
  3. package/README.zh-CN.md +570 -0
  4. package/dist/index.d.ts +6 -0
  5. package/dist/index.mjs +13 -0
  6. package/dist/index.test.d.ts +1 -0
  7. package/dist/index.test.mjs +216 -0
  8. package/dist/plugin.d.ts +61 -0
  9. package/dist/plugin.mjs +41 -0
  10. package/dist/plugin.test.d.ts +1 -0
  11. package/dist/plugin.test.mjs +631 -0
  12. package/dist/router-link.d.ts +220 -0
  13. package/dist/router-link.mjs +119 -0
  14. package/dist/router-link.test.d.ts +1 -0
  15. package/dist/router-link.test.mjs +663 -0
  16. package/dist/router-view.d.ts +31 -0
  17. package/dist/router-view.mjs +15 -0
  18. package/dist/router-view.test.d.ts +1 -0
  19. package/dist/router-view.test.mjs +676 -0
  20. package/dist/run-with-context.test.d.ts +1 -0
  21. package/dist/run-with-context.test.mjs +57 -0
  22. package/dist/use.d.ts +260 -0
  23. package/dist/use.mjs +125 -0
  24. package/dist/use.test.d.ts +1 -0
  25. package/dist/use.test.mjs +381 -0
  26. package/dist/util.d.ts +20 -0
  27. package/dist/util.mjs +49 -0
  28. package/dist/util.test.d.ts +4 -0
  29. package/dist/util.test.mjs +604 -0
  30. package/dist/vue2.d.ts +15 -0
  31. package/dist/vue2.mjs +0 -0
  32. package/dist/vue3.d.ts +13 -0
  33. package/dist/vue3.mjs +0 -0
  34. package/package.json +85 -0
  35. package/src/index.test.ts +273 -0
  36. package/src/index.ts +15 -0
  37. package/src/plugin.test.ts +812 -0
  38. package/src/plugin.ts +107 -0
  39. package/src/router-link.test.ts +830 -0
  40. package/src/router-link.ts +172 -0
  41. package/src/router-view.test.ts +840 -0
  42. package/src/router-view.ts +59 -0
  43. package/src/run-with-context.test.ts +64 -0
  44. package/src/use.test.ts +484 -0
  45. package/src/use.ts +416 -0
  46. package/src/util.test.ts +760 -0
  47. package/src/util.ts +85 -0
  48. package/src/vue2.ts +18 -0
  49. package/src/vue3.ts +15 -0
@@ -0,0 +1,570 @@
1
+ <div align="center">
2
+ <img src="https://esmx.dev/logo.svg?t=2025" width="120" alt="Esmx Logo" />
3
+ <h1>@esmx/router-vue</h1>
4
+
5
+ <div>
6
+ <a href="https://www.npmjs.com/package/@esmx/router-vue">
7
+ <img src="https://img.shields.io/npm/v/@esmx/router-vue.svg" alt="npm version" />
8
+ </a>
9
+ <a href="https://github.com/esmnext/esmx/actions/workflows/build.yml">
10
+ <img src="https://github.com/esmnext/esmx/actions/workflows/build.yml/badge.svg" alt="Build" />
11
+ </a>
12
+ <a href="https://esmx.dev/coverage/">
13
+ <img src="https://img.shields.io/badge/coverage-live%20report-brightgreen" alt="Coverage Report" />
14
+ </a>
15
+ <a href="https://nodejs.org/">
16
+ <img src="https://img.shields.io/node/v/@esmx/router-vue.svg" alt="node version" />
17
+ </a>
18
+ <a href="https://bundlephobia.com/package/@esmx/router-vue">
19
+ <img src="https://img.shields.io/bundlephobia/minzip/@esmx/router-vue" alt="size" />
20
+ </a>
21
+ </div>
22
+
23
+ <p><a href="https://github.com/esmnext/esmx/tree/master/packages/router">@esmx/router</a> 的 Vue 集成包 - 一个同时适用于 Vue 2.7+ 和 Vue 3 的通用路由器。</p>
24
+
25
+ <p>
26
+ <a href="https://github.com/esmnext/esmx/blob/master/packages/router-vue/README.md">English</a> | 中文
27
+ </p>
28
+ </div>
29
+
30
+
31
+
32
+ ## 🚀 特性
33
+
34
+ ✨ **通用 Vue 支持** - 同时支持 Vue 2.7+ 和 Vue 3
35
+ 🎯 **组合式 API 优先** - 为现代 Vue 开发而构建
36
+ 🔗 **无缝集成** - Vue Router 的替代方案
37
+ 🚀 **TypeScript 就绪** - 完整的 TypeScript 支持,出色的开发体验
38
+ ⚡ **高性能** - 为生产环境优化
39
+ 🔄 **SSR 兼容** - 支持服务端渲染
40
+
41
+ ## 📦 安装
42
+
43
+ ```bash
44
+ # npm
45
+ npm install @esmx/router @esmx/router-vue
46
+
47
+ # pnpm
48
+ pnpm add @esmx/router @esmx/router-vue
49
+
50
+ # yarn
51
+ yarn add @esmx/router @esmx/router-vue
52
+ ```
53
+
54
+ ## 🚀 快速开始
55
+
56
+ ### Vue 3
57
+
58
+ ```typescript
59
+ import { createApp, h } from 'vue';
60
+ import { Router, RouterMode } from '@esmx/router';
61
+ import { RouterPlugin, useProvideRouter } from '@esmx/router-vue';
62
+ import App from './App.vue';
63
+
64
+ const routes = [
65
+ { path: '/', component: () => import('./views/Home.vue') },
66
+ { path: '/about', component: () => import('./views/About.vue') }
67
+ ];
68
+
69
+ const router = new Router({
70
+ routes,
71
+ mode: RouterMode.history
72
+ });
73
+
74
+ const app = createApp({
75
+ setup() {
76
+ useProvideRouter(router);
77
+ return {};
78
+ },
79
+ render: () => h(App)
80
+ });
81
+
82
+ // 安装插件
83
+ app.use(RouterPlugin);
84
+
85
+ app.mount('#app');
86
+ ```
87
+
88
+ ### Vue 2.7+
89
+
90
+ ```typescript
91
+ import Vue from 'vue';
92
+ import { Router, RouterMode } from '@esmx/router';
93
+ import { RouterPlugin, useProvideRouter } from '@esmx/router-vue';
94
+ import App from './App.vue';
95
+
96
+ const routes = [
97
+ { path: '/', component: () => import('./views/Home.vue') },
98
+ { path: '/about', component: () => import('./views/About.vue') }
99
+ ];
100
+
101
+ const router = new Router({
102
+ routes,
103
+ mode: RouterMode.history
104
+ });
105
+
106
+ // 安装插件
107
+ Vue.use(RouterPlugin);
108
+
109
+ new Vue({
110
+ setup() {
111
+ useProvideRouter(router);
112
+ },
113
+ render: h => h(App)
114
+ }).$mount('#app');
115
+ ```
116
+
117
+ ## 基础用法
118
+
119
+ ### 模板用法
120
+
121
+ ```vue
122
+ <template>
123
+ <div id="app">
124
+ <nav>
125
+ <RouterLink to="/">首页</RouterLink>
126
+ <RouterLink to="/about">关于</RouterLink>
127
+ <RouterLink to="/users/123">用户资料</RouterLink>
128
+ </nav>
129
+
130
+ <!-- 路由组件将在这里渲染 -->
131
+ <RouterView />
132
+ </div>
133
+ </template>
134
+ ```
135
+
136
+ ### 组合式 API
137
+
138
+ ```vue
139
+ <script setup lang="ts">
140
+ import { useRouter, useRoute } from '@esmx/router-vue';
141
+ import { watch } from 'vue';
142
+
143
+ const router = useRouter();
144
+ const route = useRoute();
145
+
146
+ // 编程式导航
147
+ const goToAbout = () => {
148
+ router.push('/about');
149
+ };
150
+
151
+ const goBack = () => {
152
+ router.back();
153
+ };
154
+
155
+ // 监听路由变化
156
+ watch(() => route.path, (newPath) => {
157
+ // 处理路由变化逻辑
158
+ });
159
+ </script>
160
+
161
+ <template>
162
+ <div>
163
+ <h1>{{ route.meta?.title || '页面' }}</h1>
164
+ <p>当前路径: {{ route.path }}</p>
165
+ <p>路由参数: {{ JSON.stringify(route.params) }}</p>
166
+ <p>查询参数: {{ JSON.stringify(route.query) }}</p>
167
+
168
+ <button @click="goToAbout">前往关于页</button>
169
+ <button @click="goBack">返回</button>
170
+ </div>
171
+ </template>
172
+ ```
173
+
174
+ ### 选项式 API
175
+
176
+ ```vue
177
+ <script>
178
+ import { defineComponent } from 'vue';
179
+ import { getRouter, getRoute } from '@esmx/router-vue';
180
+
181
+ export default defineComponent({
182
+ mounted() {
183
+ const router = getRouter(this);
184
+ const route = getRoute(this);
185
+
186
+ // 访问当前路由信息
187
+ },
188
+
189
+ methods: {
190
+ navigate() {
191
+ const router = getRouter(this);
192
+ router.push('/dashboard');
193
+ }
194
+ }
195
+ });
196
+ </script>
197
+ ```
198
+
199
+ ## 📚 API 参考
200
+
201
+ ### 组件
202
+
203
+ #### RouterLink
204
+
205
+ 用于创建导航链接的组件。
206
+
207
+ **属性:**
208
+
209
+ | 属性 | 类型 | 默认值 | 描述 |
210
+ |------|------|---------|-------------|
211
+ | `to` | `string` \| `RouteLocationInput` | - | 目标路由位置 |
212
+ | `type` | `RouterLinkType` | `'push'` | 导航类型 (`'push'` \| `'replace'` \| `'pushWindow'` \| `'replaceWindow'` \| `'pushLayer'`) |
213
+ | `exact` | `RouteMatchType` | `'include'` | 激活状态匹配方式 (`'include'` \| `'exact'` \| `'route'`) |
214
+ | `activeClass` | `string` | - | 激活状态的 CSS 类名 |
215
+ | `event` | `string` \| `string[]` | `'click'` | 触发导航的事件 |
216
+ | `tag` | `string` | `'a'` | 要渲染的 HTML 标签 |
217
+ | `layerOptions` | `RouterLayerOptions` | - | 弹层导航选项 (与 `type="pushLayer"` 一起使用) |
218
+
219
+ **用法:**
220
+
221
+ ```vue
222
+ <template>
223
+ <!-- 基础链接 -->
224
+ <RouterLink to="/home">首页</RouterLink>
225
+
226
+ <!-- 替换导航 -->
227
+ <RouterLink to="/login" type="replace">登录</RouterLink>
228
+
229
+ <!-- 自定义样式 -->
230
+ <RouterLink
231
+ to="/dashboard"
232
+ active-class="nav-active"
233
+ exact="exact"
234
+ >
235
+ 仪表板
236
+ </RouterLink>
237
+
238
+ <!-- 自定义标签 -->
239
+ <RouterLink to="/submit" tag="button" class="btn">
240
+ 提交
241
+ </RouterLink>
242
+ </template>
243
+ ```
244
+
245
+ #### RouterView
246
+
247
+ 渲染匹配路由组件的组件。
248
+
249
+ **用法:**
250
+
251
+ ```vue
252
+ <template>
253
+ <div>
254
+ <!-- 根级路由在这里渲染 -->
255
+ <RouterView />
256
+
257
+ <!-- 嵌套路由会在子 RouterView 组件中渲染 -->
258
+ <!-- 每个 RouterView 会自动处理正确的深度 -->
259
+ </div>
260
+ </template>
261
+ ```
262
+
263
+ ### 组合式 API
264
+
265
+ #### useRouter()
266
+
267
+ 获取用于导航的路由器实例。
268
+
269
+ ```typescript
270
+ function useRouter(): Router
271
+ ```
272
+
273
+ **用法:**
274
+
275
+ ```vue
276
+ <script setup>
277
+ import { useRouter } from '@esmx/router-vue';
278
+
279
+ const router = useRouter();
280
+
281
+ const navigate = () => {
282
+ router.push('/about');
283
+ };
284
+ </script>
285
+ ```
286
+
287
+ #### useRoute()
288
+
289
+ 获取当前路由信息(响应式)。
290
+
291
+ ```typescript
292
+ function useRoute(): Route
293
+ ```
294
+
295
+ **用法:**
296
+
297
+ ```vue
298
+ <script setup>
299
+ import { useRoute } from '@esmx/router-vue';
300
+
301
+ const route = useRoute();
302
+
303
+ // 访问路由属性
304
+ // route.path - 当前路径
305
+ // route.params - 路由参数
306
+ // route.query - 查询参数
307
+ // route.meta - 路由元数据
308
+ </script>
309
+ ```
310
+
311
+ #### useProvideRouter()
312
+
313
+ 为子组件提供路由上下文。
314
+
315
+ ```typescript
316
+ function useProvideRouter(router: Router): void
317
+ ```
318
+
319
+ **用法:**
320
+
321
+ ```typescript
322
+ import { Router, RouterMode } from '@esmx/router';
323
+ import { useProvideRouter } from '@esmx/router-vue';
324
+
325
+ const router = new Router({
326
+ routes,
327
+ mode: RouterMode.history
328
+ });
329
+
330
+ // 在应用的 setup 函数中
331
+ setup() {
332
+ useProvideRouter(router);
333
+ }
334
+ ```
335
+
336
+ #### useLink()
337
+
338
+ 为自定义导航组件创建响应式链接助手。
339
+
340
+ ```typescript
341
+ function useLink(props: RouterLinkProps): ComputedRef<RouterLinkResolved>
342
+ ```
343
+
344
+ **用法:**
345
+
346
+ ```vue
347
+ <script setup>
348
+ import { useLink } from '@esmx/router-vue';
349
+
350
+ const link = useLink({
351
+ to: '/home',
352
+ type: 'push',
353
+ exact: 'include'
354
+ }).value;
355
+ </script>
356
+
357
+ <template>
358
+ <a
359
+ v-bind="link.attributes"
360
+ v-on="link.createEventHandlers()"
361
+ :class="{ active: link.isActive }"
362
+ >
363
+ 自定义链接
364
+ </a>
365
+ </template>
366
+ ```
367
+
368
+ ### 选项式 API
369
+
370
+ #### getRouter()
371
+
372
+ 在选项式 API 组件中获取路由器实例。
373
+
374
+ ```typescript
375
+ function getRouter(instance: VueInstance): Router
376
+ ```
377
+
378
+ #### getRoute()
379
+
380
+ 在选项式 API 组件中获取当前路由。
381
+
382
+ ```typescript
383
+ function getRoute(instance: VueInstance): Route
384
+ ```
385
+
386
+ ### 插件
387
+
388
+ #### RouterPlugin
389
+
390
+ 全局注册 RouterLink 和 RouterView 组件的 Vue 插件。
391
+
392
+ ```typescript
393
+ const RouterPlugin = {
394
+ install(app: App): void
395
+ }
396
+ ```
397
+
398
+ **用法:**
399
+
400
+ ```typescript
401
+ // Vue 3
402
+ app.use(RouterPlugin);
403
+
404
+ // Vue 2
405
+ Vue.use(RouterPlugin);
406
+ ```
407
+
408
+ ## TypeScript 支持
409
+
410
+ 此包为 Vue 2.7+ 和 Vue 3 提供完整的 TypeScript 支持。对于选项式 API 用法,包会自动为 Vue 组件实例增强 `$router` 和 `$route` 属性,允许您在模板和组件方法中直接访问它们。
411
+
412
+ ```typescript
413
+ // 选项式 API 类型增强(自动)
414
+ declare module 'vue/types/vue' {
415
+ interface Vue {
416
+ readonly $router: Router;
417
+ readonly $route: Route;
418
+ }
419
+ }
420
+ ```
421
+
422
+ **选项式 API 用法:**
423
+
424
+ ```vue
425
+ <template>
426
+ <div>
427
+ <!-- 直接访问,无需 'this.' -->
428
+ <p>当前路径: {{ $route.path }}</p>
429
+ <button @click="navigate">跳转到关于页面</button>
430
+ </div>
431
+ </template>
432
+
433
+ <script lang="ts">
434
+ import { defineComponent } from 'vue';
435
+
436
+ export default defineComponent({
437
+ methods: {
438
+ navigate() {
439
+ // TypeScript 能够识别 $router 和 $route
440
+ this.$router.push('/about');
441
+ // Access current route: this.$route.path
442
+ }
443
+ }
444
+ });
445
+ </script>
446
+ ```
447
+
448
+ ## 高级用法
449
+
450
+ ### 自定义链接组件
451
+
452
+ ```vue
453
+ <script setup lang="ts">
454
+ import { useLink } from '@esmx/router-vue';
455
+ import type { RouterLinkProps } from '@esmx/router';
456
+
457
+ interface Props extends RouterLinkProps {
458
+ icon?: string;
459
+ disabled?: boolean;
460
+ }
461
+
462
+ const props = defineProps<Props>();
463
+
464
+ const link = useLink(props).value;
465
+ </script>
466
+
467
+ <template>
468
+ <button
469
+ v-bind="link.attributes"
470
+ v-on="link.createEventHandlers()"
471
+ :class="{
472
+ active: link.isActive,
473
+ disabled: disabled
474
+ }"
475
+ :disabled="disabled"
476
+ >
477
+ <i v-if="icon" :class="icon" />
478
+ <slot />
479
+ </button>
480
+ </template>
481
+ ```
482
+
483
+ ### 组件中的路由守卫
484
+
485
+ ```vue
486
+ <script setup>
487
+ import { useRouter, useRoute } from '@esmx/router-vue';
488
+ import { onMounted, onBeforeUnmount } from 'vue';
489
+
490
+ const router = useRouter();
491
+ const route = useRoute();
492
+
493
+ onMounted(() => {
494
+ // 添加路由守卫
495
+ const unregister = router.beforeEach((to, from) => {
496
+ // 检查路由是否需要认证(isAuthenticated 是你的认证函数)
497
+ if (to.meta?.requiresAuth && !isAuthenticated()) {
498
+ return '/login';
499
+ }
500
+ });
501
+
502
+ // 组件卸载时清理
503
+ onBeforeUnmount(unregister);
504
+ });
505
+ </script>
506
+ ```
507
+
508
+ ## 从 Vue Router 迁移
509
+
510
+ ### 主要差异
511
+
512
+ 1. **路由器创建**: 使用 `@esmx/router` 的 `new Router()` 构造函数
513
+ 2. **上下文提供**: 使用 `useProvideRouter()` 而非路由器安装
514
+ 3. **组件注册**: 使用 `RouterPlugin` 进行全局组件注册
515
+
516
+ ### 迁移示例
517
+
518
+ **之前 (Vue Router):**
519
+
520
+ ```typescript
521
+ import { createRouter, createWebHistory } from 'vue-router';
522
+
523
+ const router = createRouter({
524
+ history: createWebHistory(),
525
+ routes
526
+ });
527
+
528
+ app.use(router);
529
+ ```
530
+
531
+ **之后 (@esmx/router-vue):**
532
+
533
+ ```typescript
534
+ import { Router, RouterMode } from '@esmx/router';
535
+ import { RouterPlugin, useProvideRouter } from '@esmx/router-vue';
536
+ import { createApp, h } from 'vue';
537
+ import App from './App.vue';
538
+
539
+ const router = new Router({
540
+ routes,
541
+ mode: RouterMode.history
542
+ });
543
+
544
+ const app = createApp({
545
+ setup() {
546
+ useProvideRouter(router);
547
+ return {};
548
+ },
549
+ render: () => h(App)
550
+ });
551
+
552
+ app.use(RouterPlugin);
553
+ ```
554
+
555
+ ## 浏览器支持
556
+
557
+ - **现代浏览器**:支持 ES 模块 (`import`/`export`) 和动态导入 (`import()`) 的浏览器
558
+
559
+ ## 贡献
560
+
561
+ 我们欢迎贡献!请随时提交 issues 和 pull requests。
562
+
563
+ ## 📄 许可证
564
+
565
+ MIT © [Esmx 团队](https://github.com/esmnext/esmx)
566
+
567
+ ## 相关包
568
+
569
+ - [@esmx/router](https://github.com/esmnext/esmx/tree/master/packages/router) - 核心路由包
570
+ - [@esmx/core](https://github.com/esmnext/esmx/tree/master/packages/core) - Esmx 核心框架
@@ -0,0 +1,6 @@
1
+ export { RouterPlugin } from './plugin';
2
+ export { RouterLink } from './router-link';
3
+ export { RouterView } from './router-view';
4
+ export { getRoute, getRouter, getRouterViewDepth, useLink, useProvideRouter, useRoute, useRouter, useRouterViewDepth } from './use';
5
+ export type * from './vue2';
6
+ export type * from './vue3';
package/dist/index.mjs ADDED
@@ -0,0 +1,13 @@
1
+ export { RouterPlugin } from "./plugin.mjs";
2
+ export { RouterLink } from "./router-link.mjs";
3
+ export { RouterView } from "./router-view.mjs";
4
+ export {
5
+ getRoute,
6
+ getRouter,
7
+ getRouterViewDepth,
8
+ useLink,
9
+ useProvideRouter,
10
+ useRoute,
11
+ useRouter,
12
+ useRouterViewDepth
13
+ } from "./use.mjs";
@@ -0,0 +1 @@
1
+ export {};