vitarx-router 4.0.0-beta.25 → 4.0.0-beta.26
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.
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { createView, isFunction, isPlainObject, logger } from 'vitarx';
|
|
2
|
+
import { isExternalLink } from '../core/index.js';
|
|
2
3
|
import { useLink } from '../core/shared/index.js';
|
|
3
4
|
const EXTRA_PROPS = [
|
|
4
5
|
'to',
|
|
5
6
|
'replace',
|
|
6
7
|
'viewTransition',
|
|
8
|
+
'exactMatchMode',
|
|
7
9
|
'disabled',
|
|
8
10
|
'callback',
|
|
9
11
|
'onclick',
|
|
@@ -41,7 +43,7 @@ const EXTRA_PROPS = [
|
|
|
41
43
|
export function RouterLink(props, location) {
|
|
42
44
|
const link = useLink(props);
|
|
43
45
|
if (__VITARX_DEV__) {
|
|
44
|
-
if (!link.route.value) {
|
|
46
|
+
if (!link.route.value && !isExternalLink(link.href.value)) {
|
|
45
47
|
logger.warn(`[RouterLink] No match found for to: ${isPlainObject(props.to) ? JSON.stringify(props.to) : String(props.to)}`, location);
|
|
46
48
|
}
|
|
47
49
|
}
|
|
@@ -49,7 +49,7 @@ export function isNavIndex(val) {
|
|
|
49
49
|
*/
|
|
50
50
|
export function hasOnlyChangeHash(route1, route2) {
|
|
51
51
|
return (route1.hash !== route2.hash &&
|
|
52
|
-
route1.
|
|
52
|
+
route1.matched.at(-1) === route2.matched.at(-1) &&
|
|
53
53
|
isDeepEqual(route1.query, route2.query));
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
@@ -590,6 +590,8 @@ export class Router {
|
|
|
590
590
|
if (!context.to)
|
|
591
591
|
return null;
|
|
592
592
|
if (hasOnlyChangeHash(context.to, context.from)) {
|
|
593
|
+
// 更新路由位置的 hash 值并触发 hashUpdate 回调
|
|
594
|
+
this._routeLocation.hash = context.to.hash;
|
|
593
595
|
this._routeLocation.href = context.to.href;
|
|
594
596
|
this.hashUpdate?.(context.to);
|
|
595
597
|
context.result.state = NavState.success;
|
package/dist/core/router/web.js
CHANGED
|
@@ -140,9 +140,14 @@ export class WebRouter extends Router {
|
|
|
140
140
|
if ('el' in target && target.el) {
|
|
141
141
|
const { el, ...rest } = target;
|
|
142
142
|
if (isString(el)) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
let element = null;
|
|
144
|
+
try {
|
|
145
|
+
element = document.querySelector(el);
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
logger.warn(`[Router] Invalid selector "${el}", skipping scroll to element`, e);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
146
151
|
if (element) {
|
|
147
152
|
if (element.scrollIntoView) {
|
|
148
153
|
element.scrollIntoView(rest);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Computed } from 'vitarx';
|
|
2
|
-
import type { NavigateResult, NavTarget, RouteIndex, RouteLocation
|
|
3
|
-
|
|
4
|
-
type
|
|
2
|
+
import type { NavigateResult, NavTarget, RouteIndex, RouteLocation } from '../types/index.js';
|
|
3
|
+
type LinkToTarget<T extends RouteIndex = RouteIndex> = NavTarget<T> | T | string;
|
|
4
|
+
export type LinkExactMatchMode = 'path' | 'href' | 'hash' | 'query';
|
|
5
5
|
export interface UseLinkOptions<T extends RouteIndex = RouteIndex> {
|
|
6
6
|
/**
|
|
7
7
|
* 要跳转的目标
|
|
@@ -23,6 +23,17 @@ export interface UseLinkOptions<T extends RouteIndex = RouteIndex> {
|
|
|
23
23
|
* @default false
|
|
24
24
|
*/
|
|
25
25
|
viewTransition?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* 精确匹配模式
|
|
28
|
+
*
|
|
29
|
+
* - 'path':精确匹配路径
|
|
30
|
+
* - 'href':精确匹配完整链接
|
|
31
|
+
* - 'hash':精确匹配路径和锚点
|
|
32
|
+
* - 'query':精确匹配路径和查询参数
|
|
33
|
+
*
|
|
34
|
+
* @default 'path'
|
|
35
|
+
*/
|
|
36
|
+
exactMatchMode?: LinkExactMatchMode;
|
|
26
37
|
}
|
|
27
38
|
export interface UseLinkReturn {
|
|
28
39
|
/**
|
|
@@ -88,6 +99,7 @@ export declare function isPathExactMatch(currentPath: string, targetPath: string
|
|
|
88
99
|
* @param props.to - 要跳转的目标,可以是路由目标对象、路由索引、带查询参数的路径字符串、哈希值或 HTTP/HTTPS 链接。
|
|
89
100
|
* @param [props.replace] - 是否使用 `router.replace()` 而不是 `router.push()`。优先级低于 `to.replace`。默认为 `false`。
|
|
90
101
|
* @param [props.viewTransition] - 如果支持则使用 `document.startViewTransition()` 进行视图过渡。默认为 `false`。
|
|
102
|
+
* @param [props.exactMatchMode] - 精确匹配模式。可选值有:'path'、'href'、'hash'、'query'。默认为 'path'。
|
|
91
103
|
* @returns 返回一个包含链接属性和导航方法的对象。
|
|
92
104
|
* @returns {Computed<string>} returns.href - 链接的 `href` 属性值。
|
|
93
105
|
* @returns {Computed<RouteLocation | null>} returns.route - 匹配的路由信息,如果未匹配则返回 `null`。
|
package/dist/core/shared/link.js
CHANGED
|
@@ -2,7 +2,7 @@ import { computed, isPlainObject, isString } from 'vitarx';
|
|
|
2
2
|
import { NavState } from '../common/constant.js';
|
|
3
3
|
import { isExternalLink, isNavTarget, isRoutePath } from '../common/utils.js';
|
|
4
4
|
import { useRouter } from './inject.js';
|
|
5
|
-
import { cloneRouteLocation, parseQuery, removeTrailingSlash } from './utils.js';
|
|
5
|
+
import { cloneRouteLocation, parseQuery, removeTrailingSlash, stringifyQuery } from './utils.js';
|
|
6
6
|
/**
|
|
7
7
|
* 处理视图转换
|
|
8
8
|
* @param callback
|
|
@@ -63,6 +63,7 @@ export function isPathExactMatch(currentPath, targetPath) {
|
|
|
63
63
|
* @param props.to - 要跳转的目标,可以是路由目标对象、路由索引、带查询参数的路径字符串、哈希值或 HTTP/HTTPS 链接。
|
|
64
64
|
* @param [props.replace] - 是否使用 `router.replace()` 而不是 `router.push()`。优先级低于 `to.replace`。默认为 `false`。
|
|
65
65
|
* @param [props.viewTransition] - 如果支持则使用 `document.startViewTransition()` 进行视图过渡。默认为 `false`。
|
|
66
|
+
* @param [props.exactMatchMode] - 精确匹配模式。可选值有:'path'、'href'、'hash'、'query'。默认为 'path'。
|
|
66
67
|
* @returns 返回一个包含链接属性和导航方法的对象。
|
|
67
68
|
* @returns {Computed<string>} returns.href - 链接的 `href` 属性值。
|
|
68
69
|
* @returns {Computed<RouteLocation | null>} returns.route - 匹配的路由信息,如果未匹配则返回 `null`。
|
|
@@ -95,7 +96,7 @@ export function useLink(props) {
|
|
|
95
96
|
else {
|
|
96
97
|
return null;
|
|
97
98
|
}
|
|
98
|
-
//
|
|
99
|
+
// 处理路由路径
|
|
99
100
|
if (isString(target.index)) {
|
|
100
101
|
// 兼容纯锚点连接跳转
|
|
101
102
|
if (target.index.startsWith('#')) {
|
|
@@ -150,7 +151,20 @@ export function useLink(props) {
|
|
|
150
151
|
const matchedRoute = route.value;
|
|
151
152
|
if (!matchedRoute)
|
|
152
153
|
return false;
|
|
153
|
-
|
|
154
|
+
const isMatched = isPathExactMatch(router.route.path, matchedRoute.path);
|
|
155
|
+
if (!isMatched)
|
|
156
|
+
return false;
|
|
157
|
+
const mode = props.exactMatchMode || 'path';
|
|
158
|
+
switch (mode) {
|
|
159
|
+
case 'href':
|
|
160
|
+
return router.route.href === matchedRoute.href;
|
|
161
|
+
case 'hash':
|
|
162
|
+
return router.route.hash === matchedRoute.hash;
|
|
163
|
+
case 'query':
|
|
164
|
+
return stringifyQuery(router.route.query) === stringifyQuery(matchedRoute.query);
|
|
165
|
+
default:
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
154
168
|
});
|
|
155
169
|
/**
|
|
156
170
|
* 导航处理函数
|
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.26",
|
|
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",
|
|
@@ -55,6 +55,9 @@
|
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"vite": {
|
|
57
57
|
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"vitarx": {
|
|
60
|
+
"optional": true
|
|
58
61
|
}
|
|
59
62
|
},
|
|
60
63
|
"dependencies": {
|