vitarx-router 4.0.0-beta.21 → 4.0.0-beta.22
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/dist/core/common/utils.js +1 -1
- package/dist/core/common/variable.js +1 -1
- package/dist/core/router/manager.d.ts +6 -4
- package/dist/core/router/manager.js +14 -15
- package/dist/core/router/router.js +1 -1
- package/dist/core/shared/link.js +1 -1
- package/dist/core/shared/utils.d.ts +5 -4
- package/dist/core/shared/utils.js +11 -8
- package/package.json +1 -1
|
@@ -71,7 +71,7 @@ export function parseHashContent(hashContent) {
|
|
|
71
71
|
// 同样限制分割数为 2,防止路径中包含 ?
|
|
72
72
|
const [pathname, queryString] = pathAndQuery.split('?', 2);
|
|
73
73
|
// 3. 格式化路径
|
|
74
|
-
path = normalizePath(pathname
|
|
74
|
+
path = pathname ? normalizePath(pathname) : '/';
|
|
75
75
|
// 4. 解析查询参数
|
|
76
76
|
if (queryString) {
|
|
77
77
|
query = parseQuery(queryString);
|
|
@@ -97,7 +97,7 @@ export function mergePathVariable(path, params) {
|
|
|
97
97
|
return String(value).replace(/\s+/g, '_');
|
|
98
98
|
});
|
|
99
99
|
// 使用 formatPath 处理可能出现的双斜杠 (如 /user//) 或首尾斜杠问题
|
|
100
|
-
return normalizePath(fullPath);
|
|
100
|
+
return normalizePath(fullPath, true);
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* 合并两个路由模式对象
|
|
@@ -9,7 +9,9 @@ export interface RouteManagerOptions {
|
|
|
9
9
|
/**
|
|
10
10
|
* 是否启用严格模式
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* 启用后路径匹配将严格匹配即 /user/ 结尾存在斜杠会匹配失败
|
|
13
|
+
*
|
|
14
|
+
* 禁用后路径匹配将宽匹配即 /user/ 会匹配 /user
|
|
13
15
|
*
|
|
14
16
|
* @default false
|
|
15
17
|
*/
|
|
@@ -23,8 +25,8 @@ export interface RouteManagerOptions {
|
|
|
23
25
|
/**
|
|
24
26
|
* 是否启用索引回退匹配。
|
|
25
27
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
+
* 开启后,当访问深层index路径(如 /user/index)未匹配时,
|
|
29
|
+
* 会尝试移除index路径(/user)再次进行匹配。
|
|
28
30
|
* 匹配成功则渲染组件,且保持 URL 不变。
|
|
29
31
|
*
|
|
30
32
|
* 仅支持匹配静态路径,不做动态路径匹配!
|
|
@@ -126,7 +128,7 @@ export declare class RouteManager {
|
|
|
126
128
|
* @returns 规范化后的路径(根据 ignoreCase 配置转换为小写)
|
|
127
129
|
* @private
|
|
128
130
|
*/
|
|
129
|
-
private
|
|
131
|
+
private toLookupPath;
|
|
130
132
|
/**
|
|
131
133
|
* 根据路径查找路由
|
|
132
134
|
*
|
|
@@ -127,7 +127,7 @@ export class RouteManager {
|
|
|
127
127
|
* @returns 规范化后的路径(根据 ignoreCase 配置转换为小写)
|
|
128
128
|
* @private
|
|
129
129
|
*/
|
|
130
|
-
|
|
130
|
+
toLookupPath(path) {
|
|
131
131
|
return this.config.ignoreCase ? path.toLowerCase() : path;
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
@@ -137,7 +137,7 @@ export class RouteManager {
|
|
|
137
137
|
* @returns 路由记录对象,如果未找到则返回 undefined
|
|
138
138
|
*/
|
|
139
139
|
findByPath(path) {
|
|
140
|
-
const normalizedPath = this.
|
|
140
|
+
const normalizedPath = this.toLookupPath(path);
|
|
141
141
|
return this.staticRoutes.get(normalizedPath) ?? this.aliasRoutes.get(normalizedPath) ?? null;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
@@ -183,9 +183,7 @@ export class RouteManager {
|
|
|
183
183
|
normalizedPath = normalizedPath.slice(0, -1);
|
|
184
184
|
}
|
|
185
185
|
// 1. 标准化路径
|
|
186
|
-
const lookupPath = this.
|
|
187
|
-
? normalizedPath.toLowerCase()
|
|
188
|
-
: normalizedPath;
|
|
186
|
+
const lookupPath = this.toLookupPath(normalizedPath);
|
|
189
187
|
// 2. 静态路由精确匹配
|
|
190
188
|
const staticRoute = this.staticRoutes.get(lookupPath);
|
|
191
189
|
if (staticRoute) {
|
|
@@ -197,14 +195,14 @@ export class RouteManager {
|
|
|
197
195
|
return { path, route: aliasRoute, params: {} };
|
|
198
196
|
}
|
|
199
197
|
// 3. 动态路由匹配
|
|
200
|
-
const pathSegments =
|
|
198
|
+
const pathSegments = path.split('/').filter(Boolean);
|
|
201
199
|
const segmentCount = pathSegments.length;
|
|
202
200
|
const dynamicCandidates = this.dynamicRoutes.get(segmentCount);
|
|
203
201
|
if (dynamicCandidates) {
|
|
204
202
|
for (const { regex, route } of dynamicCandidates) {
|
|
205
203
|
regex.lastIndex = 0;
|
|
206
204
|
// 执行正则匹配
|
|
207
|
-
const regexResult = regex.exec(
|
|
205
|
+
const regexResult = regex.exec(path);
|
|
208
206
|
if (regexResult) {
|
|
209
207
|
const params = {};
|
|
210
208
|
// 解析捕获组参数
|
|
@@ -222,6 +220,7 @@ export class RouteManager {
|
|
|
222
220
|
}
|
|
223
221
|
}
|
|
224
222
|
}
|
|
223
|
+
// 4. 结尾斜杠索引回退匹配
|
|
225
224
|
if (lookupPath.endsWith('/index') && this.config.fallbackIndex) {
|
|
226
225
|
const fallbackPath = lookupPath.slice(0, -6);
|
|
227
226
|
const fallbackRoute = this.staticRoutes.get(fallbackPath || '/');
|
|
@@ -354,14 +353,14 @@ export class RouteManager {
|
|
|
354
353
|
// 删除当前路由
|
|
355
354
|
this.routes.delete(route);
|
|
356
355
|
// 删除静态路由映射
|
|
357
|
-
this.staticRoutes.delete(this.
|
|
356
|
+
this.staticRoutes.delete(this.toLookupPath(route.path));
|
|
358
357
|
// 删除命名路由映射
|
|
359
358
|
if (route.name)
|
|
360
359
|
this.namedRoutes.delete(route.name);
|
|
361
360
|
// 删除别名映射
|
|
362
361
|
if (route.aliases) {
|
|
363
362
|
for (const alias of route.aliases) {
|
|
364
|
-
this.aliasRoutes.delete(this.
|
|
363
|
+
this.aliasRoutes.delete(this.toLookupPath(alias));
|
|
365
364
|
// 如果别名是动态路由,也需要从 dynamicRoutes 中移除
|
|
366
365
|
if (isVariablePath(alias)) {
|
|
367
366
|
this.removeAliasDynamicRoute(alias, route);
|
|
@@ -462,7 +461,7 @@ export class RouteManager {
|
|
|
462
461
|
record.parent = parent;
|
|
463
462
|
}
|
|
464
463
|
const rawPath = route.path.trim();
|
|
465
|
-
record.path = normalizePath(parent ? `${parent.path}/${rawPath}` : `/${rawPath}
|
|
464
|
+
record.path = normalizePath(parent ? `${parent.path}/${rawPath}` : `/${rawPath}`, true);
|
|
466
465
|
if (route.name) {
|
|
467
466
|
record.name = route.name;
|
|
468
467
|
}
|
|
@@ -513,13 +512,13 @@ export class RouteManager {
|
|
|
513
512
|
aliasPath = parent.path;
|
|
514
513
|
}
|
|
515
514
|
else if (rawAlias.startsWith('/')) {
|
|
516
|
-
aliasPath = normalizePath(rawAlias);
|
|
515
|
+
aliasPath = normalizePath(rawAlias, true);
|
|
517
516
|
}
|
|
518
517
|
else if (!parent) {
|
|
519
|
-
aliasPath = normalizePath(`/${rawAlias}
|
|
518
|
+
aliasPath = normalizePath(`/${rawAlias}`, true);
|
|
520
519
|
}
|
|
521
520
|
else {
|
|
522
|
-
aliasPath = normalizePath(`${parent.path}/${rawAlias}
|
|
521
|
+
aliasPath = normalizePath(`${parent.path}/${rawAlias}`, true);
|
|
523
522
|
}
|
|
524
523
|
record.aliases.push(aliasPath);
|
|
525
524
|
}
|
|
@@ -552,7 +551,7 @@ export class RouteManager {
|
|
|
552
551
|
this.registerDynamicRoute(route, route.fullPattern);
|
|
553
552
|
}
|
|
554
553
|
else {
|
|
555
|
-
const path = this.
|
|
554
|
+
const path = this.toLookupPath(route.path);
|
|
556
555
|
// 检查是否已存在相同路径的路由
|
|
557
556
|
if (this.staticRoutes.has(path)) {
|
|
558
557
|
// 抛出错误:检测到重复的路由路径
|
|
@@ -564,7 +563,6 @@ export class RouteManager {
|
|
|
564
563
|
// 注册别名
|
|
565
564
|
if (route.aliases && route.aliases.length > 0) {
|
|
566
565
|
for (const alias of route.aliases) {
|
|
567
|
-
const aliasPath = this.normalizePath(alias);
|
|
568
566
|
if (isVariablePath(alias)) {
|
|
569
567
|
if (!validateAliasVariables(route.pattern, alias)) {
|
|
570
568
|
throw new Error(`[Router] Alias "${alias}" variables do not match route "${route.path}" pattern`);
|
|
@@ -573,6 +571,7 @@ export class RouteManager {
|
|
|
573
571
|
this.registerDynamicRoute(route, regex, alias);
|
|
574
572
|
}
|
|
575
573
|
else {
|
|
574
|
+
const aliasPath = this.toLookupPath(alias);
|
|
576
575
|
if (route.pattern && route.pattern.length > 0) {
|
|
577
576
|
throw new Error(`[Router] Alias "${alias}" for dynamic route "${route.path}" must contain variables`);
|
|
578
577
|
}
|
|
@@ -965,7 +965,7 @@ export class Router {
|
|
|
965
965
|
const queryStr = stringifyQuery(query);
|
|
966
966
|
const href = `${path}${queryStr}${hashStr}`;
|
|
967
967
|
return this.config.mode === 'hash'
|
|
968
|
-
? normalizePath(`${this.config.base}
|
|
968
|
+
? normalizePath(`${this.config.base}#${href}`)
|
|
969
969
|
: normalizePath(`${this.config.base}${href}`);
|
|
970
970
|
}
|
|
971
971
|
/**
|
package/dist/core/shared/link.js
CHANGED
|
@@ -17,19 +17,20 @@ export declare function stringifyQuery(obj: Record<string, string>): `?${string}
|
|
|
17
17
|
/**
|
|
18
18
|
* 归一化path
|
|
19
19
|
*
|
|
20
|
-
*
|
|
20
|
+
* 去除所有空格、替换重复的斜杠
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* normalizePath('/ foo') // '/foo'
|
|
24
|
-
* normalizePath('/foo/') // '/foo'
|
|
24
|
+
* normalizePath('/foo/') // '/foo/'
|
|
25
25
|
* normalizePath('/foo/bar') // '/foo/bar'
|
|
26
26
|
* normalizePath('foo/') // '/foo'
|
|
27
|
+
* normalizePath('/foo/',true) // '/foo'
|
|
27
28
|
*
|
|
28
29
|
* @param {string} path - 路径字符串
|
|
29
|
-
* @param
|
|
30
|
+
* @param {boolean} removeEndSlash - 是否去除尾随斜杠
|
|
30
31
|
* @return {string} - 格式化后的路径字符串
|
|
31
32
|
*/
|
|
32
|
-
export declare function normalizePath(path: string,
|
|
33
|
+
export declare function normalizePath(path: string, removeEndSlash?: boolean): `/${string}`;
|
|
33
34
|
/**
|
|
34
35
|
* 克隆路由位置对象
|
|
35
36
|
*
|
|
@@ -28,24 +28,27 @@ export function stringifyQuery(obj) {
|
|
|
28
28
|
/**
|
|
29
29
|
* 归一化path
|
|
30
30
|
*
|
|
31
|
-
*
|
|
31
|
+
* 去除所有空格、替换重复的斜杠
|
|
32
32
|
*
|
|
33
33
|
* @example
|
|
34
34
|
* normalizePath('/ foo') // '/foo'
|
|
35
|
-
* normalizePath('/foo/') // '/foo'
|
|
35
|
+
* normalizePath('/foo/') // '/foo/'
|
|
36
36
|
* normalizePath('/foo/bar') // '/foo/bar'
|
|
37
37
|
* normalizePath('foo/') // '/foo'
|
|
38
|
+
* normalizePath('/foo/',true) // '/foo'
|
|
38
39
|
*
|
|
39
40
|
* @param {string} path - 路径字符串
|
|
40
|
-
* @param
|
|
41
|
+
* @param {boolean} removeEndSlash - 是否去除尾随斜杠
|
|
41
42
|
* @return {string} - 格式化后的路径字符串
|
|
42
43
|
*/
|
|
43
|
-
export function normalizePath(path,
|
|
44
|
+
export function normalizePath(path, removeEndSlash = false) {
|
|
44
45
|
// 去除所有空格 处理重复//
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
let normalizedPath = `/${path.trim()}`.replace(/\s+/g, '').replace(/\/+/g, '/');
|
|
47
|
+
if (removeEndSlash && normalizedPath.endsWith('/') && normalizedPath !== '/') {
|
|
48
|
+
normalizedPath = normalizedPath.replace(/\/$/, '');
|
|
49
|
+
}
|
|
50
|
+
// 去除尾随斜杠
|
|
51
|
+
return normalizedPath;
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* 克隆路由位置对象
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitarx-router",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.22",
|
|
4
4
|
"description": "Official routing solution for Vitarx framework with declarative routing, navigation guards, dynamic routes, file-based routing with HMR, and full TypeScript support.",
|
|
5
5
|
"author": "ZhuChonglin <8210856@qq.com>",
|
|
6
6
|
"license": "MIT",
|