@oiij/auto-router 0.0.3 → 0.0.4

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 CHANGED
@@ -13,13 +13,11 @@ Use auto-Router 是一个 Vue Router 工具库,为 Vue 3 应用提供自动路
13
13
 
14
14
  - 🔄 自动解析和排序路由(支持数字前缀排序)
15
15
  - 📊 路由扁平化处理
16
- - 🎯 支持嵌套路由元数据继承
17
16
  - 📝 自动规范化路由名称
18
17
 
19
18
  ### Keep-Alive 管理 💾
20
19
 
21
20
  - 🚀 自动管理页面缓存
22
- - 📦 基于路由元数据的缓存配置
23
21
  - 🎨 支持动态缓存控制
24
22
 
25
23
  ### 加载状态管理 ⏳
@@ -56,13 +54,41 @@ yarn add @oiij/auto-router
56
54
 
57
55
  ## 快速开始 🌟
58
56
 
59
- ### 基础使用
57
+ ### 1. 安装插件
58
+
59
+ 在 Vue 应用中安装 `createAutoRouter` 插件,必须在 Vue Router 之后安装:
60
+
61
+ ```ts
62
+ import { createAutoRouter } from '@oiij/auto-router'
63
+ import { createApp } from 'vue'
64
+ import { createRouter, createWebHistory } from 'vue-router'
65
+
66
+ import { routes } from 'vue-router/auto-routes' // 自动生成的路由
67
+ import App from './App.vue'
68
+
69
+ const app = createApp(App)
70
+ const router = createRouter({
71
+ history: createWebHistory(),
72
+ routes
73
+ })
74
+
75
+ // 必须先安装 Vue Router
76
+ app.use(router)
77
+ // 然后安装自动路由插件
78
+ app.use(createAutoRouter(router, routes))
79
+
80
+ app.mount('#app')
81
+ ```
82
+
83
+ ### 2. 在组件中使用
84
+
85
+ 在 Vue 组件中使用 `useAutoRouter` 获取路由实例:
60
86
 
61
87
  ```vue
62
88
  <script setup>
63
89
  import { useAutoRouter } from '@oiij/auto-router'
64
90
 
65
- const { loading, routes, currentRoutePath } = useAutoRouter()
91
+ const { loading, routes, flattenRoutes } = useAutoRouter()
66
92
  </script>
67
93
 
68
94
  <template>
@@ -71,14 +97,14 @@ const { loading, routes, currentRoutePath } = useAutoRouter()
71
97
  加载中...
72
98
  </div>
73
99
  <div v-else>
74
- <p>当前路由: {{ currentRoutePath }}</p>
100
+ <h2>路由列表</h2>
75
101
  <nav>
76
102
  <router-link
77
103
  v-for="route in routes"
78
104
  :key="route.path"
79
105
  :to="route.path"
80
106
  >
81
- {{ route.meta?.title }}
107
+ {{ route.path }}
82
108
  </router-link>
83
109
  </nav>
84
110
  </div>
package/dist/index.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { AutoRouterInstance } from "./setup-auto-router.mjs";
2
2
  import * as vue0 from "vue";
3
3
  import { App } from "vue";
4
- import * as vue_router0 from "vue-router";
5
4
  import { RouteRecordRaw, Router } from "vue-router";
6
5
 
7
6
  //#region src/index.d.ts
@@ -19,7 +18,12 @@ import { RouteRecordRaw, Router } from "vue-router";
19
18
  * </script>
20
19
  * ```
21
20
  */
22
- declare function useAutoRouter(): AutoRouterInstance;
21
+ declare function useAutoRouter(): {
22
+ loading: vue0.ComputedRef<boolean>;
23
+ routesRaw: readonly RouteRecordRaw[];
24
+ routes: RouteRecordRaw[];
25
+ flattenRoutes: RouteRecordRaw[];
26
+ };
23
27
  /**
24
28
  * 创建自动路由插件
25
29
  *
@@ -50,9 +54,6 @@ declare function createAutoRouter(router: Router, routes: readonly RouteRecordRa
50
54
  routesRaw: readonly RouteRecordRaw[];
51
55
  routes: RouteRecordRaw[];
52
56
  flattenRoutes: RouteRecordRaw[];
53
- keepAlivePath: vue0.ComputedRef<string[]>;
54
- currentRoute: vue0.ComputedRef<vue_router0.RouteLocationNormalizedLoaded>;
55
- currentRoutePath: vue0.ComputedRef<string>;
56
57
  install(app: App): void;
57
58
  };
58
59
  //#endregion
package/dist/plugin.mjs CHANGED
@@ -14,14 +14,11 @@
14
14
  * ```
15
15
  */
16
16
  function appendRouterMeta(route) {
17
- const sortMatch = route.path.match(/(\d+)_/);
18
- const sortNum = sortMatch ? Number(sortMatch[1]) : null;
19
- if (sortNum !== null && !Number.isNaN(sortNum)) route.addToMeta({ sort: sortNum });
20
- if (route.name) {
21
- const newName = route.name.replace(/\d+_/g, "");
22
- route.name = newName.startsWith("/") ? newName : `/${newName}`;
23
- if (route.path !== "") route.path = route.name;
24
- }
17
+ const reg = /(\d+)[_-]/g;
18
+ const sort = route.path.match(/(\d+)[_-]/)?.[1];
19
+ if (sort) route.addToMeta({ sort: Number(sort) });
20
+ route.path = route.path.replace(reg, "");
21
+ if (route.name) route.name = route.name.replace(reg, "");
25
22
  }
26
23
 
27
24
  //#endregion
@@ -1,39 +1,64 @@
1
- import { ComputedRef } from "vue";
2
- import { RouteLocationNormalizedLoaded, RouteRecordRaw, Router } from "vue-router";
1
+ import * as vue1 from "vue";
2
+ import { RouteRecordRaw, Router } from "vue-router";
3
3
 
4
4
  //#region src/setup-auto-router.d.ts
5
+ declare module 'vue-router' {
6
+ interface RouteMeta {
7
+ sort?: number;
8
+ }
9
+ }
5
10
  /**
6
- * 自动路由实例接口
11
+ * 设置自动路由
12
+ *
13
+ * 解析路由配置,提供路由工具方法和状态管理
14
+ *
15
+ * @param router - Vue Router 实例
16
+ * @param routesRaw - 原始路由配置数组
17
+ * @returns 自动路由实例,包含路由配置和工具方法
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * import { setupAutoRouter } from '@oiij/auto-router'
22
+ * import { router } from './router'
23
+ * import { routes } from 'vue-router/auto-routes'
24
+ *
25
+ * const autoRouter = setupAutoRouter(router, routes)
26
+ * console.log(autoRouter.routes) // 排序后的路由
27
+ * console.log(autoRouter.flattenRoutes) // 扁平化路由
28
+ * ```
7
29
  */
8
- type AutoRouterInstance = {
30
+ declare function setupAutoRouter(router: Router, routesRaw: readonly RouteRecordRaw[]): {
9
31
  /**
10
- * 加载状态
32
+ * 路由加载状态
33
+ *
34
+ * @type {import('vue').ComputedRef<boolean>}
11
35
  */
12
- loading: ComputedRef<boolean>;
36
+ loading: vue1.ComputedRef<boolean>;
13
37
  /**
14
38
  * 原始路由配置
39
+ *
40
+ * @type {readonly RouteRecordRaw[]}
15
41
  */
16
42
  routesRaw: readonly RouteRecordRaw[];
17
43
  /**
18
44
  * 解析并排序后的路由配置
45
+ *
46
+ * @type {RouteRecordRaw[]}
19
47
  */
20
48
  routes: RouteRecordRaw[];
21
49
  /**
22
- * 扁平化的路由列表(将所有子路由提取到一级)
50
+ * 扁平化的路由配置
51
+ *
52
+ * @type {RouteRecordRaw[]}
23
53
  */
24
54
  flattenRoutes: RouteRecordRaw[];
25
- /**
26
- * 需要缓存的路由路径列表
27
- */
28
- keepAlivePath: ComputedRef<string[]>;
29
- /**
30
- * 当前路由
31
- */
32
- currentRoute: ComputedRef<RouteLocationNormalizedLoaded>;
33
- /**
34
- * 当前路由路径
35
- */
36
- currentRoutePath: ComputedRef<string>;
37
55
  };
56
+ /**
57
+ * 自动路由实例类型
58
+ *
59
+ * @remarks
60
+ * 由 setupAutoRouter 函数返回的对象类型
61
+ */
62
+ type AutoRouterInstance = ReturnType<typeof setupAutoRouter>;
38
63
  //#endregion
39
64
  export { AutoRouterInstance };
@@ -3,83 +3,109 @@ import { cloneDeep } from "es-toolkit";
3
3
 
4
4
  //#region src/setup-auto-router.ts
5
5
  /**
6
- * 解析路由配置
6
+ * 深度排序路由配置
7
7
  *
8
- * 处理以下逻辑:
9
- * 1. 从子路由的 index 页面继承 group 元数据
10
- * 2. 将空路径的子路由路径设置为父路由路径
11
- * 3. 根据 sort 元数据排序路由
8
+ * 递归地对路由配置进行排序,包括所有嵌套的子路由
12
9
  *
13
- * @param routes - 原始路由配置
14
- * @returns 解析后的路由配置
10
+ * @param routes - 原始路由配置数组
11
+ * @returns 排序后的路由配置数组
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const sortedRoutes = deepSortRoutes([
16
+ * { path: '/about', meta: { sort: 2 } },
17
+ * { path: '/home', meta: { sort: 1 } }
18
+ * ])
19
+ * // 结果: [{ path: '/home', ... }, { path: '/about', ... }]
20
+ * ```
15
21
  */
16
- function parseRoutes(routes) {
17
- return routes.map((route) => {
18
- const indexMeta = (route.children?.find((f) => f.path === ""))?.meta?.group;
22
+ function deepSortRoutes(routes) {
23
+ return routes.toSorted((a, b) => (a.meta?.sort ?? Infinity) - (b.meta?.sort ?? Infinity)).map((route) => {
19
24
  return {
20
25
  ...route,
21
- meta: {
22
- ...route.meta,
23
- ...indexMeta
24
- },
25
- children: route.children?.map((child) => ({
26
- ...child,
27
- path: child.path === "" ? route.path : child.path
28
- })).toSorted((a, b) => (a.meta?.sort ?? Infinity) - (b.meta?.sort ?? Infinity))
26
+ children: route.children ? deepSortRoutes(route.children) : void 0
29
27
  };
30
- }).toSorted((a, b) => (a.meta?.sort ?? Infinity) - (b.meta?.sort ?? Infinity));
28
+ });
31
29
  }
32
30
  /**
33
31
  * 扁平化路由配置
34
32
  *
35
- * 将嵌套的路由结构展平为一维数组
33
+ * 将嵌套的路由结构展平为一维数组,包含所有层级的路由
36
34
  *
37
- * @param routes - 路由配置
35
+ * @param routes - 路由配置数组
38
36
  * @returns 扁平化后的路由数组
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const flattened = flattenDeepRoutes([
41
+ * {
42
+ * path: '/user',
43
+ * children: [{ path: '/user/profile' }]
44
+ * }
45
+ * ])
46
+ * // 结果: [{ path: '/user', ... }, { path: '/user/profile', ... }]
47
+ * ```
39
48
  */
40
- function flattenRoutes(routes) {
41
- return cloneDeep(routes).flatMap((route) => route.children ?? route);
49
+ function flattenDeepRoutes(routes) {
50
+ return routes.flatMap((route) => {
51
+ const flattened = [route];
52
+ if (route.children && route.children.length > 0) flattened.push(...flattenDeepRoutes(route.children));
53
+ return flattened;
54
+ });
42
55
  }
43
56
  /**
44
57
  * 设置自动路由
45
58
  *
46
- * 解析路由配置,提供路由工具方法
59
+ * 解析路由配置,提供路由工具方法和状态管理
47
60
  *
48
61
  * @param router - Vue Router 实例
49
- * @returns 自动路由实例
62
+ * @param routesRaw - 原始路由配置数组
63
+ * @returns 自动路由实例,包含路由配置和工具方法
50
64
  *
51
65
  * @example
52
66
  * ```ts
53
67
  * import { setupAutoRouter } from '@oiij/auto-router'
54
68
  * import { router } from './router'
69
+ * import { routes } from 'vue-router/auto-routes'
55
70
  *
56
- * const autoRouter = setupAutoRouter(router)
57
- * console.log(autoRouter.routes) // 解析后的路由
71
+ * const autoRouter = setupAutoRouter(router, routes)
72
+ * console.log(autoRouter.routes) // 排序后的路由
58
73
  * console.log(autoRouter.flattenRoutes) // 扁平化路由
59
74
  * ```
60
75
  */
61
76
  function setupAutoRouter(router, routesRaw) {
77
+ /**
78
+ * 路由加载状态
79
+ *
80
+ * @remarks
81
+ * 通过导航守卫自动管理,在路由切换时设置为 true,切换完成后设置为 false
82
+ */
62
83
  const loading = ref(false);
63
- router.beforeEach((to, from, next) => {
84
+ router.beforeEach(() => {
64
85
  loading.value = true;
65
- next();
66
86
  });
67
87
  router.afterEach(() => {
68
88
  loading.value = false;
69
89
  });
70
- const routes = parseRoutes(cloneDeep(routesRaw));
71
- const flattenRoutesCache = flattenRoutes(routes);
72
- const keepAlivePath = computed(() => flattenRoutesCache.filter((f) => f.meta?.keepAlive).map((m) => m.path));
73
- const currentRoute = computed(() => router.currentRoute.value);
74
- const currentRoutePath = computed(() => currentRoute.value.path);
90
+ /**
91
+ * 解析并排序后的路由配置
92
+ *
93
+ * @remarks
94
+ * 使用 deepSortRoutes 对路由进行深度排序,确保所有层级的路由都按 sort 元数据排序
95
+ */
96
+ const routes = deepSortRoutes(cloneDeep(routesRaw));
97
+ /**
98
+ * 扁平化的路由配置
99
+ *
100
+ * @remarks
101
+ * 使用 flattenDeepRoutes 将嵌套的路由结构展平为一维数组,方便后续处理
102
+ */
103
+ const flattenRoutes = flattenDeepRoutes(routes);
75
104
  return {
76
105
  loading: computed(() => loading.value),
77
106
  routesRaw,
78
107
  routes,
79
- flattenRoutes: flattenRoutesCache,
80
- keepAlivePath,
81
- currentRoute,
82
- currentRoutePath
108
+ flattenRoutes
83
109
  };
84
110
  }
85
111
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oiij/auto-router",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.4",
5
5
  "description": "Vue Router utilities and composables for Vue 3",
6
6
  "author": "oiij",
7
7
  "license": "MIT",
@@ -26,9 +26,6 @@
26
26
  "./plugin": {
27
27
  "types": "./dist/plugin.d.mts",
28
28
  "import": "./dist/plugin.mjs"
29
- },
30
- "./auto-router": {
31
- "types": "./auto-router.d.ts"
32
29
  }
33
30
  },
34
31
  "main": "./dist/index.mjs",
@@ -37,7 +34,6 @@
37
34
  "files": [
38
35
  "LICENSE",
39
36
  "README.md",
40
- "auto-router.d.ts",
41
37
  "dist",
42
38
  "package.json"
43
39
  ],
package/auto-router.d.ts DELETED
@@ -1,93 +0,0 @@
1
- /* eslint-disable */
2
- /* prettier-ignore */
3
- // biome-ignore format: off
4
- // biome-ignore lint: off
5
- // @ts-nocheck
6
- // Vue Router 路由元数据类型扩展
7
- // 这个文件扩展了 vue-router 的 RouteMeta 接口
8
- // 确保此文件包含在项目的 tsconfig.json 中
9
-
10
- import 'vue-router'
11
-
12
- // 为了确保这个文件被当作一个模块,添加至少一个 export 声明
13
- export {}
14
-
15
- declare module 'vue-router' {
16
- interface RouteMeta {
17
- /**
18
- * 路由标题
19
- */
20
- title?: string
21
-
22
- /**
23
- * 路由描述
24
- */
25
- description?: string
26
-
27
- /**
28
- * 路由图标
29
- */
30
- icon?: string
31
-
32
- /**
33
- * 图标颜色
34
- */
35
- iconColor?: string
36
-
37
- /**
38
- * 排序权重(数字越小越靠前)
39
- */
40
- sort?: number
41
-
42
- /**
43
- * 布局组件名称
44
- */
45
- layout?: string
46
-
47
- /**
48
- * 过渡动画名称
49
- */
50
- transitionName?: string
51
-
52
- /**
53
- * 是否启用 Keep-Alive 缓存
54
- */
55
- keepAlive?: boolean
56
-
57
- /**
58
- * 是否为根路由
59
- */
60
- root?: boolean
61
-
62
- /**
63
- * 路由分组信息(用于导航菜单等)
64
- */
65
- group?: {
66
- /**
67
- * 分组标题
68
- */
69
- title?: string
70
-
71
- /**
72
- * 分组描述
73
- */
74
- description?: string
75
-
76
- /**
77
- * 分组图标
78
- */
79
- icon?: string
80
-
81
- /**
82
- * 分组图标颜色
83
- */
84
- iconColor?: string
85
-
86
- /**
87
- * 分组排序权重
88
- */
89
- sort?: number
90
- }
91
- }
92
- }
93
-