vitarx-router 1.0.0-beta.6 → 1.0.0-beta.7
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.
|
@@ -11,9 +11,9 @@ declare interface Route {
|
|
|
11
11
|
* 生成路由索引类型声明
|
|
12
12
|
*
|
|
13
13
|
* @param {Route[]} routes - 路由表
|
|
14
|
-
* @param {string[]}
|
|
15
|
-
* @param {string} [writePath] - 要写入的路径,完整的路径!例如'/Users/Vitarx/vitarx/route.type.d.ts'
|
|
14
|
+
* @param {string[]} custom - 自定义的名称或路径,例如['/home', 'home']
|
|
15
|
+
* @param {string} [writePath] - 要写入的路径,完整的路径!例如'/Users/Vitarx/vitarx/route.type.d.ts',默认为当前工作目录下的route.type.d.ts
|
|
16
16
|
* @return {void}
|
|
17
17
|
*/
|
|
18
|
-
export default function make(routes: Route[],
|
|
18
|
+
export default function make(routes: Route[], custom?: string[], writePath?: string): void;
|
|
19
19
|
export {};
|
|
@@ -1,49 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
36
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
37
|
-
if (ar || !(i in from)) {
|
|
38
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
39
|
-
ar[i] = from[i];
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
43
|
-
};
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.default = make;
|
|
46
|
-
var fs = __importStar(require("node:fs"));
|
|
1
|
+
import * as fs from 'node:fs';
|
|
47
2
|
/**
|
|
48
3
|
* 格式化path
|
|
49
4
|
*
|
|
@@ -52,7 +7,7 @@ var fs = __importStar(require("node:fs"));
|
|
|
52
7
|
*/
|
|
53
8
|
function formatPath(path) {
|
|
54
9
|
// 去除所有空格 处理重复//
|
|
55
|
-
path =
|
|
10
|
+
path = `/${path}`.replace(/\s+/g, '').replace(/\/+/g, '/');
|
|
56
11
|
if (!path.length)
|
|
57
12
|
return '/';
|
|
58
13
|
if (path === '/' || path === '/#/')
|
|
@@ -66,13 +21,12 @@ function formatPath(path) {
|
|
|
66
21
|
* @return {{ paths: string[], names: string[] }} - 路由索引对象,包含所有路由路径和名称
|
|
67
22
|
*/
|
|
68
23
|
function buildRouteIndex(routes) {
|
|
69
|
-
|
|
70
|
-
|
|
24
|
+
const paths = [];
|
|
25
|
+
const names = [];
|
|
71
26
|
// 递归遍历路由,拼接路径
|
|
72
|
-
function traverse(route, parentPath) {
|
|
73
|
-
if (parentPath === void 0) { parentPath = ''; }
|
|
27
|
+
function traverse(route, parentPath = '') {
|
|
74
28
|
// 如果是路由组,拼接路径并继续遍历子路由
|
|
75
|
-
|
|
29
|
+
const fullPath = formatPath(parentPath ? `${parentPath}/${route.path}` : route.path);
|
|
76
30
|
// 如果有widget,记录路径
|
|
77
31
|
if (route.widget) {
|
|
78
32
|
paths.push(fullPath);
|
|
@@ -83,32 +37,30 @@ function buildRouteIndex(routes) {
|
|
|
83
37
|
}
|
|
84
38
|
// 如果有子路由,递归遍历
|
|
85
39
|
if (route.children && route.children.length > 0) {
|
|
86
|
-
route.children.forEach(
|
|
40
|
+
route.children.forEach(childRoute => traverse(childRoute, fullPath));
|
|
87
41
|
}
|
|
88
42
|
}
|
|
89
43
|
// 遍历所有的根路由
|
|
90
|
-
routes.forEach(
|
|
44
|
+
routes.forEach(route => traverse(route));
|
|
91
45
|
return {
|
|
92
|
-
paths
|
|
93
|
-
names
|
|
46
|
+
paths,
|
|
47
|
+
names
|
|
94
48
|
};
|
|
95
49
|
}
|
|
96
50
|
/**
|
|
97
51
|
* 生成路由索引类型声明
|
|
98
52
|
*
|
|
99
53
|
* @param {Route[]} routes - 路由表
|
|
100
|
-
* @param {string[]}
|
|
101
|
-
* @param {string} [writePath] - 要写入的路径,完整的路径!例如'/Users/Vitarx/vitarx/route.type.d.ts'
|
|
54
|
+
* @param {string[]} custom - 自定义的名称或路径,例如['/home', 'home']
|
|
55
|
+
* @param {string} [writePath] - 要写入的路径,完整的路径!例如'/Users/Vitarx/vitarx/route.type.d.ts',默认为当前工作目录下的route.type.d.ts
|
|
102
56
|
* @return {void}
|
|
103
57
|
*/
|
|
104
|
-
function make(routes,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
var _a = buildRouteIndex(routes), paths = _a.paths, names = _a.names;
|
|
108
|
-
var all = __spreadArray(__spreadArray(__spreadArray([], paths, true), names, true), dynamic, true);
|
|
58
|
+
export default function make(routes, custom = [], writePath = '') {
|
|
59
|
+
const { paths, names } = buildRouteIndex(routes);
|
|
60
|
+
const all = [...paths, ...names, ...custom];
|
|
109
61
|
// 构造类型声明字符串
|
|
110
|
-
|
|
62
|
+
const typeDeclaration = `type VitarxRouterRouteIndexTyped = ${all.map(route => `'${route}'`).join(' | ')};`;
|
|
111
63
|
if (!writePath)
|
|
112
|
-
writePath =
|
|
64
|
+
writePath = `${process.cwd()}/route.type.d.ts`;
|
|
113
65
|
fs.writeFileSync(writePath, typeDeclaration, { encoding: 'utf-8' });
|
|
114
66
|
}
|
package/dist/vitarx-router.es.js
CHANGED
|
@@ -5,7 +5,7 @@ var H = (e) => {
|
|
|
5
5
|
var K = (e, t, i) => t in e ? q(e, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : e[t] = i;
|
|
6
6
|
var u = (e, t, i) => K(e, typeof t != "symbol" ? t + "" : t, i), I = (e, t, i) => t.has(e) || H("Cannot " + i);
|
|
7
7
|
var f = (e, t, i) => (I(e, t, "read from private field"), i ? i.call(e) : t.get(e)), _ = (e, t, i) => t.has(e) ? H("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, i), v = (e, t, i, n) => (I(e, t, "write to private field"), n ? n.call(e, i) : t.set(e, i), i);
|
|
8
|
-
import { reactive as J, shallowReactive as Q, markRaw as k, createElement as
|
|
8
|
+
import { reactive as J, shallowReactive as Q, markRaw as k, createElement as O, LazyWidget as X, deepClone as Z, isDeepEqual as S, Widget as M, shallowRef as N, inject as tt, provide as et, watch as it, Fragment as nt, Computed as L, isString as st } from "vitarx";
|
|
9
9
|
var p = /* @__PURE__ */ ((e) => (e[e.success = 0] = "success", e[e.aborted = 1] = "aborted", e[e.cancelled = 2] = "cancelled", e[e.duplicated = 3] = "duplicated", e[e.not_matched = 4] = "not_matched", e[e.exception = 5] = "exception", e))(p || {});
|
|
10
10
|
const rt = ["path", "hash", "index", "fullPath"];
|
|
11
11
|
function ot(e, t) {
|
|
@@ -409,7 +409,7 @@ const R = class R {
|
|
|
409
409
|
const n = t.widget;
|
|
410
410
|
if (!Object.prototype.hasOwnProperty.call(n, i)) return;
|
|
411
411
|
const s = n[i];
|
|
412
|
-
return Rt(s) ?
|
|
412
|
+
return Rt(s) ? O(X, { children: s, key: t.path }) : O(s);
|
|
413
413
|
}
|
|
414
414
|
/**
|
|
415
415
|
* 后退到上一个历史记录
|
|
@@ -551,8 +551,8 @@ const R = class R {
|
|
|
551
551
|
let l;
|
|
552
552
|
const c = [];
|
|
553
553
|
if (i) {
|
|
554
|
-
let
|
|
555
|
-
this.suffix &&
|
|
554
|
+
let V = G(n);
|
|
555
|
+
this.suffix && V && !i.path.endsWith(V) ? l = C(i.path + V, r) : l = C(i.path, r);
|
|
556
556
|
let P = this.findParentRoute(i);
|
|
557
557
|
for (; P; )
|
|
558
558
|
P.widget && c.unshift(P), P = this.findParentRoute(P);
|
|
@@ -589,7 +589,10 @@ const R = class R {
|
|
|
589
589
|
message: "导航到相同的路由,被系统阻止!"
|
|
590
590
|
});
|
|
591
591
|
try {
|
|
592
|
-
const a = await this.onBeforeEach(
|
|
592
|
+
const a = await this.onBeforeEach(
|
|
593
|
+
c,
|
|
594
|
+
this.currentRouteLocation
|
|
595
|
+
);
|
|
593
596
|
return a === !1 ? h({
|
|
594
597
|
status: p.aborted,
|
|
595
598
|
message: "导航被前置守卫钩子阻止"
|
|
@@ -629,7 +632,10 @@ const R = class R {
|
|
|
629
632
|
completeNavigation(t, i) {
|
|
630
633
|
const n = this._currentRouteLocation;
|
|
631
634
|
if (this._completeViewRender = () => {
|
|
632
|
-
this.onScrollBehavior(this.currentRouteLocation, n, i).then(), this.onAfterEach(
|
|
635
|
+
this.onScrollBehavior(this.currentRouteLocation, n, i).then(), this.onAfterEach(
|
|
636
|
+
this.currentRouteLocation,
|
|
637
|
+
n
|
|
638
|
+
);
|
|
633
639
|
}, t)
|
|
634
640
|
this.updateRouteLocation(t);
|
|
635
641
|
else if (this._pendingReplace)
|
|
@@ -1102,11 +1108,13 @@ function $t(e) {
|
|
|
1102
1108
|
function Lt() {
|
|
1103
1109
|
return d.instance;
|
|
1104
1110
|
}
|
|
1105
|
-
function
|
|
1111
|
+
function Ot() {
|
|
1106
1112
|
return d.instance.currentRouteLocation;
|
|
1107
1113
|
}
|
|
1108
|
-
function
|
|
1109
|
-
return e
|
|
1114
|
+
function Vt(e) {
|
|
1115
|
+
return Object.defineProperty(e, U, {
|
|
1116
|
+
value: !0
|
|
1117
|
+
}), e;
|
|
1110
1118
|
}
|
|
1111
1119
|
var E, y, w, x;
|
|
1112
1120
|
const b = class b extends M {
|
|
@@ -1197,7 +1205,7 @@ const b = class b extends M {
|
|
|
1197
1205
|
* @protected
|
|
1198
1206
|
*/
|
|
1199
1207
|
build() {
|
|
1200
|
-
return this.currentElement ||
|
|
1208
|
+
return this.currentElement || O(nt);
|
|
1201
1209
|
}
|
|
1202
1210
|
/**
|
|
1203
1211
|
* 视图渲染完成通知路由器
|
|
@@ -1280,7 +1288,7 @@ class jt extends M {
|
|
|
1280
1288
|
i.stopPropagation(), i.preventDefault(), !this.isDisabled && d.instance.navigate(this.location.value).then();
|
|
1281
1289
|
}
|
|
1282
1290
|
build() {
|
|
1283
|
-
return
|
|
1291
|
+
return O("a", this.htmlProps.value);
|
|
1284
1292
|
}
|
|
1285
1293
|
}
|
|
1286
1294
|
export {
|
|
@@ -1293,7 +1301,7 @@ export {
|
|
|
1293
1301
|
$t as createRouter,
|
|
1294
1302
|
Et as defineRoute,
|
|
1295
1303
|
bt as defineRoutes,
|
|
1296
|
-
|
|
1297
|
-
|
|
1304
|
+
Vt as lazy,
|
|
1305
|
+
Ot as useRoute,
|
|
1298
1306
|
Lt as useRouter
|
|
1299
1307
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(a,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("vitarx")):typeof define=="function"&&define.amd?define(["exports","vitarx"],o):(a=typeof globalThis<"u"?globalThis:a||self,o(a.VitarxRouter={},a.Vitarx))})(this,function(a,o){"use strict";var pt=Object.defineProperty;var Y=a=>{throw TypeError(a)};var Rt=(a,o,h)=>o in a?pt(a,o,{enumerable:!0,configurable:!0,writable:!0,value:h}):a[o]=h;var d=(a,o,h)=>Rt(a,typeof o!="symbol"?o+"":o,h),U=(a,o,h)=>o.has(a)||Y("Cannot "+h);var R=(a,o,h)=>(U(a,o,"read from private field"),h?h.call(a):o.get(a)),x=(a,o,h)=>o.has(a)?Y("Cannot add the same private member more than once"):o instanceof WeakSet?o.add(a):o.set(a,h),L=(a,o,h,V)=>(U(a,o,"write to private field"),V?V.call(a,h):o.set(a,h),h);var w,E,P,_,b;var h=(e=>(e[e.success=0]="success",e[e.aborted=1]="aborted",e[e.cancelled=2]="cancelled",e[e.duplicated=3]="duplicated",e[e.not_matched=4]="not_matched",e[e.exception=5]="exception",e))(h||{});const V=["path","hash","index","fullPath"];function q(e,t){G(e.matched,t.matched),k(e.params,t.params),k(e.query,t.query),k(e.meta,t.meta);for(const i of V)e[i]!==t[i]&&(e[i]=t[i])}function G(e,t){for(let i=0;i<t.length;i++)e[i]!==t[i]&&(e[i]=t[i]);e.length>t.length&&(e.length=t.length)}function k(e,t){const i=Object.keys(e),n=Object.keys(t);for(const s of n)Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);for(const s in i)s in t||delete e[s]}function T(e){return typeof e=="boolean"||typeof e=="function"||typeof e=="object"&&e!==null}function K(e){if(e.widget===void 0)return;if(!("injectProps"in e)){e.injectProps=S(e,!0);return}const t=e.injectProps;if(typeof t=="object")J(t)?Q(e,t):X(e,t);else if(T(t))e.injectProps=S(e,t);else throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 injectProps 类型有误,它可以是布尔值、函数,亦或是一个{string:any}类型的对象。`)}function J(e){return Object.keys(e).length===1&&"default"in e}function Q(e,t){if(!T(t.default))throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 injectProps.default 类型有误,它可以是布尔值、函数,亦或是一个{string:any}类型的对象。`)}function X(e,t){for(const i of Object.keys(e.widget))if(i in t){if(!T(t[i]))throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 injectProps.${i} 类型有误,它可以是布尔值、函数,亦或是一个{string:any}类型的对象。`)}else t[i]=!0}function S(e,t){const i={};for(const n of Object.keys(e.widget))i[n]=t;return i}function Z(e){if(!("widget"in e)){if(e.children.length===0)throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 widget 属性缺失,它可以是函数式小部件、类小部件,亦或是一个惰性加载器。`);e.widget=void 0;return}if(typeof e.widget=="function")e.widget={default:e.widget};else if(typeof e.widget=="object"&&e.widget!==null){if(Object.keys(e.widget).length===0)e.widget=void 0;else for(const t in e.widget)if(typeof e.widget[t]!="function")throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 widget 命名视图 ${t} 类型有误,它可以是函数式小部件、类小部件,亦或是一个惰性加载器。`)}else throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 widget 类型有误,它可以是函数式小部件、类小部件,亦或是一个惰性加载器。`)}const W=Symbol("LazyLoader");function j(e){return/\{[^}]+}/.test(e)}function N(e){const t=e.replace(/\s+/g,""),i=/\{[\w-]+\?}/g,n=t.match(i);return n?n.length:0}function A(e){return"children"in e&&e.children!==void 0&&e.children.length>0}function tt(e,t,i,n){let s=0;const r=(f,u)=>{const O=t[f];if(O?O instanceof RegExp||(console.warn(`[Vitarx.Router][WARN]:${e} 动态路径${f}变量的自定义正则表达式必须是 RegExp 类型`),t[f]=n):t[f]=n,u)return s++,`(?:(${t[f].source}))?`;if(s)throw new Error(`[Vitarx.Router][ERROR]:动态路径 ${e} 中,可选变量 ${f} 后不能存在任何必填变量`);return`(${t[f].source})`},c=e.replace(/{([^}?]+)\?}/g,(f,u)=>r(u,!0)).replace(/{([^}]+)}/g,(f,u)=>r(u,!1)).replace(/\//g,"\\/").replace(/\/?$/,"/?"),p=i?"":"i",l=e.replace(/^\/|\/$/g,"").split("/").length;return{regex:new RegExp(`^${c}$`,p),length:l,optional:s}}function g(e){return e=`/${e}`.replace(/\s+/g,"").replace(/\/+/g,"/"),e.length?e==="/"||e==="/#/"?e:e.replace(/\/$/,""):"/"}function C(e,t){if(!j(e))return e;const i=e;return e=e.replace(/{([^}]+)\?*}/g,(n,s)=>{const r=s.endsWith("?");if(r&&(s=s.slice(0,-1)),t[s]===void 0){if(r)return"";throw new TypeError(`[Vitarx.Router.mergePathParams] 访问路由${i}时缺少参数:${s}`)}return String(t[s]).replace(/\s+/g,"_")}),g(e)}function et(e){return typeof e=="function"&&e[W]}function D(e,t){return typeof e!="string"||!e?"":(e=e.trim(),e.startsWith("#")?e:`#${e}`)}function z(e){e=decodeURIComponent(e);const t=new URLSearchParams(e.startsWith("?")?e.substring(1):e),i={};return t.forEach((n,s)=>i[s]=n),i}function it(e){const t=new URLSearchParams(e).toString();return t?`?${t}`:""}function nt(e,t,i){let n=decodeURIComponent(e.pathname),s=decodeURIComponent(e.hash),r=z(e.search);if(n=g(n.startsWith(i)?n.slice(i.length):n),t==="hash"&&s.includes("#/")){const c=s.slice(1),[p,l]=c.split("#"),[f,u]=p.split("?");n=g(f||""),s=l?`#${l}`:"",r=z(u||"")}return{index:n,hash:s,query:r}}function st(e){const t=M(e);return t&&(e=e.slice(0,-t.length)),{path:e,suffix:t}}function M(e){const t=e.match(/^(.*?)(\.[a-zA-Z0-9]+)$/);return t?t[2]:""}function ot(e){if(typeof e!="object"||e===null)return!1;const t=["index","fullPath","path","hash","params","query","matched","meta"];for(const i of t)if(!Object.prototype.hasOwnProperty.call(e,i))return!1;return!0}function rt(e){if(e.meta=e.meta||{},e.pattern=e.pattern||{},e.children=e.children||[],!Array.isArray(e.children))throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置 children 类型错误,它必须是数组类型。`);if(!e.path.trim())throw new TypeError("[Vitarx.Router][TYPE_ERROR]:路由线路配置 path 不能为空");return e.path=g(e.path),Z(e),K(e),e}const y=class y{constructor(t){d(this,"_options");d(this,"_namedRoutes",new Map);d(this,"_dynamicRoutes",new Map);d(this,"_pathRoutes",new Map);d(this,"_parentRoute",new WeakMap);d(this,"_currentTaskId",null);d(this,"_taskCounter",0);d(this,"_pendingReplace",null);d(this,"_pendingPush",null);d(this,"_scrollBehaviorHandler");d(this,"_currentRouteLocation");d(this,"_isBrowser",typeof window<"u"&&typeof window.document<"u");d(this,"_scrollBehavior","auto");if(R(y,w))throw new Error("[Vitarx.Router.constructor]:路由器实例已存在,不能创建多个实例");this._options={base:"/",strict:!1,mode:"path",scrollBehavior:"smooth",suffix:!1,pattern:/[\w.]+/,...t},this._options.base=`/${this._options.base.replace(/^\/+|\/+$/g,"")}`,this._currentRouteLocation=o.reactive({index:this._options.base,path:this._options.base,hash:"",fullPath:this._options.base,params:{},query:{},matched:o.shallowReactive([]),meta:o.markRaw({})})}static get instance(){if(!R(y,w))throw new Error("[Vitarx.Router.instance]:路由器实例未初始化");return R(y,w)}get isBrowser(){return this._isBrowser}get scrollBehavior(){return this._scrollBehavior}get options(){return this._options}get mode(){return this._options.mode}get pathRoutes(){return this._pathRoutes}get namedRoutes(){return this._namedRoutes}get dynamicRoutes(){return this._dynamicRoutes}get routes(){return this._options.routes}get basePath(){return this._options.base}get initialized(){return R(y,w)!==void 0}get suffix(){return this._options.suffix}get currentRouteLocation(){return this._currentRouteLocation}get isPendingNavigation(){return!!(this._pendingReplace||this._pendingPush)}get pendingReplaceData(){return this._pendingReplace}get pendingPushData(){return this._pendingPush}static routeView(t,i){const n=t.widget;if(!Object.prototype.hasOwnProperty.call(n,i))return;const s=n[i];return et(s)?o.createElement(o.LazyWidget,{children:s,key:t.path}):o.createElement(s)}back(){return this.go(-1)}forward(){return this.go(1)}replace(t){return typeof t=="string"?this.navigate({index:t,isReplace:!0}):(t.isReplace=!0,this.navigate(t))}push(t){return typeof t=="string"?this.navigate({index:t,isReplace:!1}):(t.isReplace=!1,this.navigate(t))}removeRoute(t,i=!0){const n=this.findRoute(t);if(n){if(A(n))for(const s of n.children)this.removeRoute(s.path,!1);this._pathRoutes.delete(n.path),n.name&&this._namedRoutes.delete(n.name),this.removeDynamicRoute(n.path),i&&this.removedFromRoutes(n)}}addRoute(t,i){if(i){const n=this.findRoute(i);if(!n)throw new Error(`[Vitarx.Router.addRoute][ERROR]:父路由${i}不存在`);this.registerRoute(t,n)}else this.registerRoute(t),this._options.routes.push(t)}findRoute(t){const i=typeof t=="object",n=i?t.index:t;if(typeof n!="string")throw new TypeError(`[Vitarx.Router.getRoute][ERROR]:路由索引${t}类型错误,必须给定字符串类型`);if(n.startsWith("/")){const s=this.matchRoute(n);return s?(s.params&&i&&(t.params=Object.assign(t.params||{},s.params)),s.route):void 0}return this.findNamedRoute(n)}findNamedRoute(t){return this._namedRoutes.get(t)}initialize(){return R(y,w)?this:(this.setupRoutes(this._options.routes),typeof this.options.scrollBehavior=="function"?this._scrollBehaviorHandler=this.options.scrollBehavior:this._scrollBehavior=this.options.scrollBehavior,this.initializeRouter(),L(y,w,this),this)}scrollTo(t){if(!(this.isBrowser||!t||typeof t!="object")){if("el"in t){const{el:i,...n}=t,s=typeof i=="string"?document.querySelector(i):i;s&&s instanceof Element?s.scrollIntoView?s.scrollIntoView({behavior:this.scrollBehavior,...n}):window.scrollTo({behavior:this.scrollBehavior,top:s.getBoundingClientRect().top+window.scrollY,left:s.getBoundingClientRect().left+window.scrollX}):console.warn(`[Vitarx.Router.scrollTo][WARN]:元素${i}不存在,无法完成滚动到目标元素操作`);return}window.scrollTo({behavior:this.scrollBehavior,...t})}}findParentRoute(t){return this._parentRoute.get(t)}createRouteLocation(t){if(ot(t))return t;const i=this.findRoute(t),{index:n,query:s={},params:r={},hash:c=""}=t;let p;const l=[];if(i){let I=M(n);this.suffix&&I&&!i.path.endsWith(I)?p=C(i.path+I,r):p=C(i.path,r);let $=this.findParentRoute(i);for(;$;)$.widget&&l.unshift($),$=this.findParentRoute($);l.push(i)}else p=g(n);const f=(i==null?void 0:i.meta)||{},u=D(c),O=this.makeFullPath(p,s,u);return{index:n,path:p,hash:u,fullPath:O,params:r,query:s,matched:l,meta:f}}navigate(t){const i=++this._taskCounter;this._currentTaskId=i;const n=()=>this._currentTaskId===i,s=o.deepClone(this.currentRouteLocation),r=async(c,p)=>{const l=this.createRouteLocation(c),f=(u={})=>({from:s,to:l,status:h.success,message:"导航成功",redirectFrom:p?t:void 0,...u});if(this.isSameNavigate(l,this.currentRouteLocation))return f({status:h.duplicated,message:"导航到相同的路由,被系统阻止!"});try{const u=await this.onBeforeEach(l,this.currentRouteLocation);return u===!1?f({status:h.aborted,message:"导航被前置守卫钩子阻止"}):n()?typeof u=="object"&&u.index!==c.index?(u.isReplace??(u.isReplace=!1),r(u,!0)):l.matched.length?(c.isReplace?(this._pendingReplace=l,this.replaceHistory(l)):(this._pendingPush=l,this.pushHistory(l)),f()):f({status:h.not_matched,message:"未匹配到任何路由规则,被系统阻止!请检测目标索引是否正确。"}):f({status:h.cancelled,message:"已被新的导航请求替代,取消此次导航!"})}catch(u){return console.error("[Vitarx.Router.navigate][ERROR]:导航时捕获到了异常",u),f({status:h.exception,message:"导航时捕获到了异常",error:u})}};return r(t,!1)}_completeViewRender(){}completeNavigation(t,i){const n=this._currentRouteLocation;if(this._completeViewRender=()=>{this.onScrollBehavior(this.currentRouteLocation,n,i).then(),this.onAfterEach(this.currentRouteLocation,n)},t)this.updateRouteLocation(t);else if(this._pendingReplace)this.updateRouteLocation(this._pendingReplace);else if(this._pendingPush)this.updateRouteLocation(this._pendingPush);else throw new Error("[Vitarx.Router.completeNavigation][ERROR]:没有处于等待状态的导航请求。");this._pendingReplace=null,this._pendingPush=null}updateQuery(t){o.isDeepEqual(this._currentRouteLocation.query,t)||(this._currentRouteLocation.query=t,this._currentRouteLocation.fullPath=this.makeFullPath(this._currentRouteLocation.path,t,this._currentRouteLocation.hash))}updateHash(t){typeof t!="string"&&console.warn(`[Vitarx.Router.updateHash][WARN]:hash值只能是字符串类型,给定${t}`);const i=D(t);i!==this._currentRouteLocation.hash&&(this._currentRouteLocation.hash=i,this._currentRouteLocation.fullPath=this.makeFullPath(this._currentRouteLocation.path,this._currentRouteLocation.query,i))}matchRoute(t){if(t=g(t),this._options.strict||(t=t.toLowerCase()),this.suffix){const{path:s,suffix:r}=st(t);if(!this.isAllowedSuffix(r))return;t=s}if(this._pathRoutes.has(t))return{route:this._pathRoutes.get(t),params:void 0};const i=t.split("/").filter(Boolean).length,n=this._dynamicRoutes.get(i);if(n){t=`${t}/`;for(const{regex:s,route:r}of n){const c=s.exec(t);if(c){const p={};return Object.keys(r.pattern).forEach((f,u)=>{p[f]=c[u+1]}),{route:r,params:p}}}}}makeFullPath(t,i,n){return n&&!n.startsWith("#")&&(n=`#${n}`),typeof i=="object"&&(i=it(i)),this.mode==="hash"?g(`${this.basePath}/#${t}${i}${n}`):g(`${this.basePath}${t}${i}${n}`)}isSameNavigate(t,i){return o.isDeepEqual(t,i)}onBeforeEach(t,i){var n;return(n=this._options.beforeEach)==null?void 0:n.call(this,t,i)}onAfterEach(t,i){var n;return(n=this._options.afterEach)==null?void 0:n.call(this,t,i)}updateRouteLocation(t){q(this._currentRouteLocation,t)}isAllowedSuffix(t){return t?this.suffix?this.suffix==="*"?!0:Array.isArray(this.suffix)?this.suffix.includes(t):this.suffix===t:!1:!0}async onScrollBehavior(t,i,n){try{if(this._scrollBehaviorHandler){const s=await this._scrollBehaviorHandler(t,i,n);s&&this.scrollTo(s)}else this.scrollTo(n)}catch(s){console.error("[Vitarx.Router.onScrollBehavior]['ERROR']:处理滚动行为时捕获到了异常",s)}}removedFromRoutes(t){const i=this.findParentRoute(t);if(i!=null&&i.children){const n=i.children.indexOf(t);n!==-1&&i.children.splice(n,1)}else{const n=this._options.routes.indexOf(t);n!==-1&&this._options.routes.splice(n,1)}}removeDynamicRoute(t){if(!j(t))return;const n=t.split("/").filter(Boolean).length,s=c=>{const p=this._dynamicRoutes.get(c);if(p){for(let l=0;l<p.length;l++)if(p[l].route.path===t){p.splice(l,1);break}}};s(n);const r=N(t);if(r>0)for(let c=1;c<=r;c++)s(n-c)}setupRoutes(t){for(const i of t)this.registerRoute(i)}registerRoute(t,i){const n=rt(t);if(i&&(n.path=g(`${i.path}${n.path}`),this._parentRoute.set(n,i)),A(n)){t.widget&&this.recordRoute(n);for(const s of n.children)this.registerRoute(s,n)}else this.recordRoute(n)}strictPath(t){return this._options.strict?t:t.toLowerCase()}recordRoute(t){if(t.name){if(t.name.startsWith("/")&&(t.name=t.name.replace(/^\//,""),console.warn(`[Vitarx.Router][WARN]:命名路由(name)不要以/开头: ${t.name},因为内部需要使用/区分path、name`)),this._namedRoutes.has(t.name))throw new Error(`[Vitarx.Router][ERROR]:检测到重复的路由名称(name): ${t.name}`);this._namedRoutes.set(t.name,t)}const i=this.strictPath(t.path);if(this._pathRoutes.has(i))throw new Error(`[Vitarx.Router][ERROR]:检测到重复的路由路径(path): ${t.path}`);this._pathRoutes.set(i,t),j(t.path)&&this.recordDynamicRoute(t)}recordDynamicRoute(t){const{regex:i,length:n,optional:s}=tt(t.path,t.pattern,this.options.strict,this.options.pattern),r=c=>{this._dynamicRoutes.has(c)||this._dynamicRoutes.set(c,[]),this._dynamicRoutes.get(c).push({regex:i,route:t})};if(r(n),s>0)for(let c=1;c<=s;c++)r(n-c)}};w=new WeakMap,x(y,w);let m=y;class F extends m{constructor(t){super(t),["path","hash"].includes(t.mode)&&(t.mode="path"),t.mode==="hash"&&this.ensureHash()}get currentRouteTarget(){return nt(window.location,this.mode,this.basePath)}get webHistory(){return window.history}go(t){this.webHistory.go(t)}initializeRouter(){window.addEventListener("popstate",this.onPopState.bind(this)),this.replace(this.currentRouteTarget).then()}pushHistory(t){this.saveCurrentScrollPosition(),this.webHistory.pushState(this.createState(t),"",t.fullPath),this.completeNavigation(t)}replaceHistory(t){var n;const i=(n=this.webHistory.state)==null?void 0:n.scrollPosition;this.webHistory.replaceState(this.createState(t),"",t.fullPath),this.completeNavigation(t,i)}saveCurrentScrollPosition(){const t={left:window.scrollX,top:window.scrollY,behavior:this.scrollBehavior};this.webHistory.replaceState({...this.webHistory.state,scrollPosition:t},"",window.location.href)}createState(t,i,n){const{matched:s,...r}=t;return typeof i=="string"&&(r.hash=i),typeof n=="object"&&(r.query=n),JSON.parse(JSON.stringify(r))}onPopState(t){var n;let i;(n=t.state)!=null&&n.index?i={index:t.state.index,hash:t.state.hash,query:t.state.query}:i=this.currentRouteTarget,this.replace(i).then(s=>{if(!s.redirectFrom&&this.mode==="hash"&&s.status!==h.success)if(s.status===h.not_matched){if(s.to.index.startsWith("/")){const r=s.to.index.slice(1),c=window.document.getElementById(r);c&&c.scrollIntoView({behavior:this.scrollBehavior}),this.updateHash(`#${r}`),this.webHistory.replaceState(this.createState(this.currentRouteLocation),"",this.currentRouteLocation.fullPath)}}else s.status===h.duplicated&&this.webHistory.replaceState(this.createState(this.currentRouteLocation),"",this.currentRouteLocation.fullPath)})}ensureHash(){const{pathname:t,search:i,hash:n}=window.location;if(!t.startsWith(this.basePath)){const s=`${this.basePath}/#${t}${i}${n}`;return window.location.replace(s)}}}class B extends m{constructor(i){super(i);d(this,"_history",[]);d(this,"_pendingGo",null);d(this,"_currentIndex",0);i.mode="memory"}get currentIndex(){return this._currentIndex}go(i){if(!i)return;const n=this.currentIndex,s=Math.max(0,Math.min(this._history.length-1,n+i));if(s===n)return;const r=this._history[s];this._pendingGo=s,this.navigate(r).then(c=>{c.status!==h.success&&(this._pendingGo=null)})}initializeRouter(){this._history.push(this.currentRouteLocation)}pushHistory(i){this._updateHistory(i,!1)}replaceHistory(i){this._updateHistory(i,!0)}_updateHistory(i,n){let s;if(this._pendingGo!==null)this._history[this._pendingGo]=i,s=this._pendingGo;else if(n)this._history[this.currentIndex]=i,s=this.currentIndex;else{const r=this.currentIndex+1;r<this._history.length?(this._history[r]=i,this._history.length=r+1,s=r):(this._history.push(i),s=this._history.length-1)}this._currentIndex=s,this.completeNavigation(i),this._pendingGo=null}}function at(...e){return e}function ct(e){return e}function ht(e){let t;return!(window!=null&&window.location)&&e.mode!=="memory"?(console.warn("当前环境非浏览器端,强制使用内存模式路由"),e.mode="memory",new B(e).initialize()):(e.mode==="memory"?t=new B(e):t=new F(e),t.initialize())}function ut(){return m.instance}function lt(){return m.instance.currentRouteLocation}function ft(e){return e[W]=!0,e}const v=class v extends o.Widget{constructor(i){super(i);x(this,P);x(this,_);x(this,b,o.shallowRef());const n=o.inject(R(v,E),-1,this);L(this,P,n+1),o.provide(R(v,E),R(this,P),this),L(this,_,this.matchedRoute),R(this,_)&&(R(this,b).value=m.routeView(R(this,_),this.name)),o.watch(this.location.matched,(s,r)=>{const c=r[this.index];c!==R(this,_)&&(L(this,_,c),R(this,b).value=c?m.routeView(c,this.name):void 0)})}get index(){return R(this,P)}get isLastView(){return this.index===this.location.matched.length-1&&this.name==="default"}get name(){return this.props.name||"default"}get matchedRoute(){return this.location.matched[R(this,P)]}get currentElement(){return R(this,b).value}get location(){return m.instance.currentRouteLocation}onMounted(){this.completeViewRender()}onUpdated(){this.completeViewRender()}build(){return this.currentElement||o.createElement(o.Fragment)}completeViewRender(){this.isLastView&&m.instance._completeViewRender()}};E=new WeakMap,P=new WeakMap,_=new WeakMap,b=new WeakMap,x(v,E,Symbol("RouterViewCounter"));let H=v;class dt extends o.Widget{constructor(i){super(i);d(this,"target");d(this,"location");d(this,"active");d(this,"htmlProps");this.target=new o.Computed(()=>o.markRaw(o.isString(i.to)?{index:i.to}:i.to)),this.location=new o.Computed(()=>{const n=m.instance.createRouteLocation(this.target.value);return n.matched.length||console.trace(`[Vitarx.RouterLink][WARN]:索引:${this.target.value.index},未匹配到任何有效的路由线路,请检查to属性是否配置正确!`),o.markRaw(n)}),this.active=new o.Computed(()=>this.location.value.fullPath===m.instance.currentRouteLocation.fullPath),this.htmlProps=new o.Computed(()=>{const n={href:this.href,onClick:s=>this.navigate(s),children:this.children,style:this.props.style,class:this.props.class};return this.isActive&&(n.active=!0),this.isDisabled&&(n.disabled=!0),n})}get isActive(){return this.active.value&&!this.isDisabled}get isDisabled(){return this.props.disabled??!1}get href(){return this.location.value.fullPath}navigate(i){i.stopPropagation(),i.preventDefault(),!this.isDisabled&&m.instance.navigate(this.location.value).then()}build(){return o.createElement("a",this.htmlProps.value)}}a.MemoryRouter=B,a.NavigateStatus=h,a.Router=m,a.RouterLink=dt,a.RouterView=H,a.WebHistoryRouter=F,a.createRouter=ht,a.defineRoute=ct,a.defineRoutes=at,a.lazy=ft,a.useRoute=lt,a.useRouter=ut,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(a,o){typeof exports=="object"&&typeof module<"u"?o(exports,require("vitarx")):typeof define=="function"&&define.amd?define(["exports","vitarx"],o):(a=typeof globalThis<"u"?globalThis:a||self,o(a.VitarxRouter={},a.Vitarx))})(this,function(a,o){"use strict";var pt=Object.defineProperty;var Y=a=>{throw TypeError(a)};var Rt=(a,o,h)=>o in a?pt(a,o,{enumerable:!0,configurable:!0,writable:!0,value:h}):a[o]=h;var d=(a,o,h)=>Rt(a,typeof o!="symbol"?o+"":o,h),U=(a,o,h)=>o.has(a)||Y("Cannot "+h);var R=(a,o,h)=>(U(a,o,"read from private field"),h?h.call(a):o.get(a)),x=(a,o,h)=>o.has(a)?Y("Cannot add the same private member more than once"):o instanceof WeakSet?o.add(a):o.set(a,h),L=(a,o,h,V)=>(U(a,o,"write to private field"),V?V.call(a,h):o.set(a,h),h);var w,E,P,_,b;var h=(e=>(e[e.success=0]="success",e[e.aborted=1]="aborted",e[e.cancelled=2]="cancelled",e[e.duplicated=3]="duplicated",e[e.not_matched=4]="not_matched",e[e.exception=5]="exception",e))(h||{});const V=["path","hash","index","fullPath"];function q(e,t){G(e.matched,t.matched),j(e.params,t.params),j(e.query,t.query),j(e.meta,t.meta);for(const i of V)e[i]!==t[i]&&(e[i]=t[i])}function G(e,t){for(let i=0;i<t.length;i++)e[i]!==t[i]&&(e[i]=t[i]);e.length>t.length&&(e.length=t.length)}function j(e,t){const i=Object.keys(e),n=Object.keys(t);for(const s of n)Object.prototype.hasOwnProperty.call(t,s)&&(e[s]=t[s]);for(const s in i)s in t||delete e[s]}function k(e){return typeof e=="boolean"||typeof e=="function"||typeof e=="object"&&e!==null}function K(e){if(e.widget===void 0)return;if(!("injectProps"in e)){e.injectProps=S(e,!0);return}const t=e.injectProps;if(typeof t=="object")J(t)?Q(e,t):X(e,t);else if(k(t))e.injectProps=S(e,t);else throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 injectProps 类型有误,它可以是布尔值、函数,亦或是一个{string:any}类型的对象。`)}function J(e){return Object.keys(e).length===1&&"default"in e}function Q(e,t){if(!k(t.default))throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 injectProps.default 类型有误,它可以是布尔值、函数,亦或是一个{string:any}类型的对象。`)}function X(e,t){for(const i of Object.keys(e.widget))if(i in t){if(!k(t[i]))throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 injectProps.${i} 类型有误,它可以是布尔值、函数,亦或是一个{string:any}类型的对象。`)}else t[i]=!0}function S(e,t){const i={};for(const n of Object.keys(e.widget))i[n]=t;return i}function Z(e){if(!("widget"in e)){if(e.children.length===0)throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 widget 属性缺失,它可以是函数式小部件、类小部件,亦或是一个惰性加载器。`);e.widget=void 0;return}if(typeof e.widget=="function")e.widget={default:e.widget};else if(typeof e.widget=="object"&&e.widget!==null){if(Object.keys(e.widget).length===0)e.widget=void 0;else for(const t in e.widget)if(typeof e.widget[t]!="function")throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 widget 命名视图 ${t} 类型有误,它可以是函数式小部件、类小部件,亦或是一个惰性加载器。`)}else throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置的 widget 类型有误,它可以是函数式小部件、类小部件,亦或是一个惰性加载器。`)}const W=Symbol("LazyLoader");function T(e){return/\{[^}]+}/.test(e)}function N(e){const t=e.replace(/\s+/g,""),i=/\{[\w-]+\?}/g,n=t.match(i);return n?n.length:0}function A(e){return"children"in e&&e.children!==void 0&&e.children.length>0}function tt(e,t,i,n){let s=0;const r=(f,u)=>{const O=t[f];if(O?O instanceof RegExp||(console.warn(`[Vitarx.Router][WARN]:${e} 动态路径${f}变量的自定义正则表达式必须是 RegExp 类型`),t[f]=n):t[f]=n,u)return s++,`(?:(${t[f].source}))?`;if(s)throw new Error(`[Vitarx.Router][ERROR]:动态路径 ${e} 中,可选变量 ${f} 后不能存在任何必填变量`);return`(${t[f].source})`},c=e.replace(/{([^}?]+)\?}/g,(f,u)=>r(u,!0)).replace(/{([^}]+)}/g,(f,u)=>r(u,!1)).replace(/\//g,"\\/").replace(/\/?$/,"/?"),p=i?"":"i",l=e.replace(/^\/|\/$/g,"").split("/").length;return{regex:new RegExp(`^${c}$`,p),length:l,optional:s}}function g(e){return e=`/${e}`.replace(/\s+/g,"").replace(/\/+/g,"/"),e.length?e==="/"||e==="/#/"?e:e.replace(/\/$/,""):"/"}function C(e,t){if(!T(e))return e;const i=e;return e=e.replace(/{([^}]+)\?*}/g,(n,s)=>{const r=s.endsWith("?");if(r&&(s=s.slice(0,-1)),t[s]===void 0){if(r)return"";throw new TypeError(`[Vitarx.Router.mergePathParams] 访问路由${i}时缺少参数:${s}`)}return String(t[s]).replace(/\s+/g,"_")}),g(e)}function et(e){return typeof e=="function"&&e[W]}function D(e,t){return typeof e!="string"||!e?"":(e=e.trim(),e.startsWith("#")?e:`#${e}`)}function z(e){e=decodeURIComponent(e);const t=new URLSearchParams(e.startsWith("?")?e.substring(1):e),i={};return t.forEach((n,s)=>i[s]=n),i}function it(e){const t=new URLSearchParams(e).toString();return t?`?${t}`:""}function nt(e,t,i){let n=decodeURIComponent(e.pathname),s=decodeURIComponent(e.hash),r=z(e.search);if(n=g(n.startsWith(i)?n.slice(i.length):n),t==="hash"&&s.includes("#/")){const c=s.slice(1),[p,l]=c.split("#"),[f,u]=p.split("?");n=g(f||""),s=l?`#${l}`:"",r=z(u||"")}return{index:n,hash:s,query:r}}function st(e){const t=M(e);return t&&(e=e.slice(0,-t.length)),{path:e,suffix:t}}function M(e){const t=e.match(/^(.*?)(\.[a-zA-Z0-9]+)$/);return t?t[2]:""}function ot(e){if(typeof e!="object"||e===null)return!1;const t=["index","fullPath","path","hash","params","query","matched","meta"];for(const i of t)if(!Object.prototype.hasOwnProperty.call(e,i))return!1;return!0}function rt(e){if(e.meta=e.meta||{},e.pattern=e.pattern||{},e.children=e.children||[],!Array.isArray(e.children))throw new TypeError(`[Vitarx.Router][TYPE_ERROR]:${e.path} 路由线路配置 children 类型错误,它必须是数组类型。`);if(!e.path.trim())throw new TypeError("[Vitarx.Router][TYPE_ERROR]:路由线路配置 path 不能为空");return e.path=g(e.path),Z(e),K(e),e}const y=class y{constructor(t){d(this,"_options");d(this,"_namedRoutes",new Map);d(this,"_dynamicRoutes",new Map);d(this,"_pathRoutes",new Map);d(this,"_parentRoute",new WeakMap);d(this,"_currentTaskId",null);d(this,"_taskCounter",0);d(this,"_pendingReplace",null);d(this,"_pendingPush",null);d(this,"_scrollBehaviorHandler");d(this,"_currentRouteLocation");d(this,"_isBrowser",typeof window<"u"&&typeof window.document<"u");d(this,"_scrollBehavior","auto");if(R(y,w))throw new Error("[Vitarx.Router.constructor]:路由器实例已存在,不能创建多个实例");this._options={base:"/",strict:!1,mode:"path",scrollBehavior:"smooth",suffix:!1,pattern:/[\w.]+/,...t},this._options.base=`/${this._options.base.replace(/^\/+|\/+$/g,"")}`,this._currentRouteLocation=o.reactive({index:this._options.base,path:this._options.base,hash:"",fullPath:this._options.base,params:{},query:{},matched:o.shallowReactive([]),meta:o.markRaw({})})}static get instance(){if(!R(y,w))throw new Error("[Vitarx.Router.instance]:路由器实例未初始化");return R(y,w)}get isBrowser(){return this._isBrowser}get scrollBehavior(){return this._scrollBehavior}get options(){return this._options}get mode(){return this._options.mode}get pathRoutes(){return this._pathRoutes}get namedRoutes(){return this._namedRoutes}get dynamicRoutes(){return this._dynamicRoutes}get routes(){return this._options.routes}get basePath(){return this._options.base}get initialized(){return R(y,w)!==void 0}get suffix(){return this._options.suffix}get currentRouteLocation(){return this._currentRouteLocation}get isPendingNavigation(){return!!(this._pendingReplace||this._pendingPush)}get pendingReplaceData(){return this._pendingReplace}get pendingPushData(){return this._pendingPush}static routeView(t,i){const n=t.widget;if(!Object.prototype.hasOwnProperty.call(n,i))return;const s=n[i];return et(s)?o.createElement(o.LazyWidget,{children:s,key:t.path}):o.createElement(s)}back(){return this.go(-1)}forward(){return this.go(1)}replace(t){return typeof t=="string"?this.navigate({index:t,isReplace:!0}):(t.isReplace=!0,this.navigate(t))}push(t){return typeof t=="string"?this.navigate({index:t,isReplace:!1}):(t.isReplace=!1,this.navigate(t))}removeRoute(t,i=!0){const n=this.findRoute(t);if(n){if(A(n))for(const s of n.children)this.removeRoute(s.path,!1);this._pathRoutes.delete(n.path),n.name&&this._namedRoutes.delete(n.name),this.removeDynamicRoute(n.path),i&&this.removedFromRoutes(n)}}addRoute(t,i){if(i){const n=this.findRoute(i);if(!n)throw new Error(`[Vitarx.Router.addRoute][ERROR]:父路由${i}不存在`);this.registerRoute(t,n)}else this.registerRoute(t),this._options.routes.push(t)}findRoute(t){const i=typeof t=="object",n=i?t.index:t;if(typeof n!="string")throw new TypeError(`[Vitarx.Router.getRoute][ERROR]:路由索引${t}类型错误,必须给定字符串类型`);if(n.startsWith("/")){const s=this.matchRoute(n);return s?(s.params&&i&&(t.params=Object.assign(t.params||{},s.params)),s.route):void 0}return this.findNamedRoute(n)}findNamedRoute(t){return this._namedRoutes.get(t)}initialize(){return R(y,w)?this:(this.setupRoutes(this._options.routes),typeof this.options.scrollBehavior=="function"?this._scrollBehaviorHandler=this.options.scrollBehavior:this._scrollBehavior=this.options.scrollBehavior,this.initializeRouter(),L(y,w,this),this)}scrollTo(t){if(!(this.isBrowser||!t||typeof t!="object")){if("el"in t){const{el:i,...n}=t,s=typeof i=="string"?document.querySelector(i):i;s&&s instanceof Element?s.scrollIntoView?s.scrollIntoView({behavior:this.scrollBehavior,...n}):window.scrollTo({behavior:this.scrollBehavior,top:s.getBoundingClientRect().top+window.scrollY,left:s.getBoundingClientRect().left+window.scrollX}):console.warn(`[Vitarx.Router.scrollTo][WARN]:元素${i}不存在,无法完成滚动到目标元素操作`);return}window.scrollTo({behavior:this.scrollBehavior,...t})}}findParentRoute(t){return this._parentRoute.get(t)}createRouteLocation(t){if(ot(t))return t;const i=this.findRoute(t),{index:n,query:s={},params:r={},hash:c=""}=t;let p;const l=[];if(i){let I=M(n);this.suffix&&I&&!i.path.endsWith(I)?p=C(i.path+I,r):p=C(i.path,r);let $=this.findParentRoute(i);for(;$;)$.widget&&l.unshift($),$=this.findParentRoute($);l.push(i)}else p=g(n);const f=(i==null?void 0:i.meta)||{},u=D(c),O=this.makeFullPath(p,s,u);return{index:n,path:p,hash:u,fullPath:O,params:r,query:s,matched:l,meta:f}}navigate(t){const i=++this._taskCounter;this._currentTaskId=i;const n=()=>this._currentTaskId===i,s=o.deepClone(this.currentRouteLocation),r=async(c,p)=>{const l=this.createRouteLocation(c),f=(u={})=>({from:s,to:l,status:h.success,message:"导航成功",redirectFrom:p?t:void 0,...u});if(this.isSameNavigate(l,this.currentRouteLocation))return f({status:h.duplicated,message:"导航到相同的路由,被系统阻止!"});try{const u=await this.onBeforeEach(l,this.currentRouteLocation);return u===!1?f({status:h.aborted,message:"导航被前置守卫钩子阻止"}):n()?typeof u=="object"&&u.index!==c.index?(u.isReplace??(u.isReplace=!1),r(u,!0)):l.matched.length?(c.isReplace?(this._pendingReplace=l,this.replaceHistory(l)):(this._pendingPush=l,this.pushHistory(l)),f()):f({status:h.not_matched,message:"未匹配到任何路由规则,被系统阻止!请检测目标索引是否正确。"}):f({status:h.cancelled,message:"已被新的导航请求替代,取消此次导航!"})}catch(u){return console.error("[Vitarx.Router.navigate][ERROR]:导航时捕获到了异常",u),f({status:h.exception,message:"导航时捕获到了异常",error:u})}};return r(t,!1)}_completeViewRender(){}completeNavigation(t,i){const n=this._currentRouteLocation;if(this._completeViewRender=()=>{this.onScrollBehavior(this.currentRouteLocation,n,i).then(),this.onAfterEach(this.currentRouteLocation,n)},t)this.updateRouteLocation(t);else if(this._pendingReplace)this.updateRouteLocation(this._pendingReplace);else if(this._pendingPush)this.updateRouteLocation(this._pendingPush);else throw new Error("[Vitarx.Router.completeNavigation][ERROR]:没有处于等待状态的导航请求。");this._pendingReplace=null,this._pendingPush=null}updateQuery(t){o.isDeepEqual(this._currentRouteLocation.query,t)||(this._currentRouteLocation.query=t,this._currentRouteLocation.fullPath=this.makeFullPath(this._currentRouteLocation.path,t,this._currentRouteLocation.hash))}updateHash(t){typeof t!="string"&&console.warn(`[Vitarx.Router.updateHash][WARN]:hash值只能是字符串类型,给定${t}`);const i=D(t);i!==this._currentRouteLocation.hash&&(this._currentRouteLocation.hash=i,this._currentRouteLocation.fullPath=this.makeFullPath(this._currentRouteLocation.path,this._currentRouteLocation.query,i))}matchRoute(t){if(t=g(t),this._options.strict||(t=t.toLowerCase()),this.suffix){const{path:s,suffix:r}=st(t);if(!this.isAllowedSuffix(r))return;t=s}if(this._pathRoutes.has(t))return{route:this._pathRoutes.get(t),params:void 0};const i=t.split("/").filter(Boolean).length,n=this._dynamicRoutes.get(i);if(n){t=`${t}/`;for(const{regex:s,route:r}of n){const c=s.exec(t);if(c){const p={};return Object.keys(r.pattern).forEach((f,u)=>{p[f]=c[u+1]}),{route:r,params:p}}}}}makeFullPath(t,i,n){return n&&!n.startsWith("#")&&(n=`#${n}`),typeof i=="object"&&(i=it(i)),this.mode==="hash"?g(`${this.basePath}/#${t}${i}${n}`):g(`${this.basePath}${t}${i}${n}`)}isSameNavigate(t,i){return o.isDeepEqual(t,i)}onBeforeEach(t,i){var n;return(n=this._options.beforeEach)==null?void 0:n.call(this,t,i)}onAfterEach(t,i){var n;return(n=this._options.afterEach)==null?void 0:n.call(this,t,i)}updateRouteLocation(t){q(this._currentRouteLocation,t)}isAllowedSuffix(t){return t?this.suffix?this.suffix==="*"?!0:Array.isArray(this.suffix)?this.suffix.includes(t):this.suffix===t:!1:!0}async onScrollBehavior(t,i,n){try{if(this._scrollBehaviorHandler){const s=await this._scrollBehaviorHandler(t,i,n);s&&this.scrollTo(s)}else this.scrollTo(n)}catch(s){console.error("[Vitarx.Router.onScrollBehavior]['ERROR']:处理滚动行为时捕获到了异常",s)}}removedFromRoutes(t){const i=this.findParentRoute(t);if(i!=null&&i.children){const n=i.children.indexOf(t);n!==-1&&i.children.splice(n,1)}else{const n=this._options.routes.indexOf(t);n!==-1&&this._options.routes.splice(n,1)}}removeDynamicRoute(t){if(!T(t))return;const n=t.split("/").filter(Boolean).length,s=c=>{const p=this._dynamicRoutes.get(c);if(p){for(let l=0;l<p.length;l++)if(p[l].route.path===t){p.splice(l,1);break}}};s(n);const r=N(t);if(r>0)for(let c=1;c<=r;c++)s(n-c)}setupRoutes(t){for(const i of t)this.registerRoute(i)}registerRoute(t,i){const n=rt(t);if(i&&(n.path=g(`${i.path}${n.path}`),this._parentRoute.set(n,i)),A(n)){t.widget&&this.recordRoute(n);for(const s of n.children)this.registerRoute(s,n)}else this.recordRoute(n)}strictPath(t){return this._options.strict?t:t.toLowerCase()}recordRoute(t){if(t.name){if(t.name.startsWith("/")&&(t.name=t.name.replace(/^\//,""),console.warn(`[Vitarx.Router][WARN]:命名路由(name)不要以/开头: ${t.name},因为内部需要使用/区分path、name`)),this._namedRoutes.has(t.name))throw new Error(`[Vitarx.Router][ERROR]:检测到重复的路由名称(name): ${t.name}`);this._namedRoutes.set(t.name,t)}const i=this.strictPath(t.path);if(this._pathRoutes.has(i))throw new Error(`[Vitarx.Router][ERROR]:检测到重复的路由路径(path): ${t.path}`);this._pathRoutes.set(i,t),T(t.path)&&this.recordDynamicRoute(t)}recordDynamicRoute(t){const{regex:i,length:n,optional:s}=tt(t.path,t.pattern,this.options.strict,this.options.pattern),r=c=>{this._dynamicRoutes.has(c)||this._dynamicRoutes.set(c,[]),this._dynamicRoutes.get(c).push({regex:i,route:t})};if(r(n),s>0)for(let c=1;c<=s;c++)r(n-c)}};w=new WeakMap,x(y,w);let m=y;class F extends m{constructor(t){super(t),["path","hash"].includes(t.mode)&&(t.mode="path"),t.mode==="hash"&&this.ensureHash()}get currentRouteTarget(){return nt(window.location,this.mode,this.basePath)}get webHistory(){return window.history}go(t){this.webHistory.go(t)}initializeRouter(){window.addEventListener("popstate",this.onPopState.bind(this)),this.replace(this.currentRouteTarget).then()}pushHistory(t){this.saveCurrentScrollPosition(),this.webHistory.pushState(this.createState(t),"",t.fullPath),this.completeNavigation(t)}replaceHistory(t){var n;const i=(n=this.webHistory.state)==null?void 0:n.scrollPosition;this.webHistory.replaceState(this.createState(t),"",t.fullPath),this.completeNavigation(t,i)}saveCurrentScrollPosition(){const t={left:window.scrollX,top:window.scrollY,behavior:this.scrollBehavior};this.webHistory.replaceState({...this.webHistory.state,scrollPosition:t},"",window.location.href)}createState(t,i,n){const{matched:s,...r}=t;return typeof i=="string"&&(r.hash=i),typeof n=="object"&&(r.query=n),JSON.parse(JSON.stringify(r))}onPopState(t){var n;let i;(n=t.state)!=null&&n.index?i={index:t.state.index,hash:t.state.hash,query:t.state.query}:i=this.currentRouteTarget,this.replace(i).then(s=>{if(!s.redirectFrom&&this.mode==="hash"&&s.status!==h.success)if(s.status===h.not_matched){if(s.to.index.startsWith("/")){const r=s.to.index.slice(1),c=window.document.getElementById(r);c&&c.scrollIntoView({behavior:this.scrollBehavior}),this.updateHash(`#${r}`),this.webHistory.replaceState(this.createState(this.currentRouteLocation),"",this.currentRouteLocation.fullPath)}}else s.status===h.duplicated&&this.webHistory.replaceState(this.createState(this.currentRouteLocation),"",this.currentRouteLocation.fullPath)})}ensureHash(){const{pathname:t,search:i,hash:n}=window.location;if(!t.startsWith(this.basePath)){const s=`${this.basePath}/#${t}${i}${n}`;return window.location.replace(s)}}}class B extends m{constructor(i){super(i);d(this,"_history",[]);d(this,"_pendingGo",null);d(this,"_currentIndex",0);i.mode="memory"}get currentIndex(){return this._currentIndex}go(i){if(!i)return;const n=this.currentIndex,s=Math.max(0,Math.min(this._history.length-1,n+i));if(s===n)return;const r=this._history[s];this._pendingGo=s,this.navigate(r).then(c=>{c.status!==h.success&&(this._pendingGo=null)})}initializeRouter(){this._history.push(this.currentRouteLocation)}pushHistory(i){this._updateHistory(i,!1)}replaceHistory(i){this._updateHistory(i,!0)}_updateHistory(i,n){let s;if(this._pendingGo!==null)this._history[this._pendingGo]=i,s=this._pendingGo;else if(n)this._history[this.currentIndex]=i,s=this.currentIndex;else{const r=this.currentIndex+1;r<this._history.length?(this._history[r]=i,this._history.length=r+1,s=r):(this._history.push(i),s=this._history.length-1)}this._currentIndex=s,this.completeNavigation(i),this._pendingGo=null}}function at(...e){return e}function ct(e){return e}function ht(e){let t;return!(window!=null&&window.location)&&e.mode!=="memory"?(console.warn("当前环境非浏览器端,强制使用内存模式路由"),e.mode="memory",new B(e).initialize()):(e.mode==="memory"?t=new B(e):t=new F(e),t.initialize())}function ut(){return m.instance}function lt(){return m.instance.currentRouteLocation}function ft(e){return Object.defineProperty(e,W,{value:!0}),e}const v=class v extends o.Widget{constructor(i){super(i);x(this,P);x(this,_);x(this,b,o.shallowRef());const n=o.inject(R(v,E),-1,this);L(this,P,n+1),o.provide(R(v,E),R(this,P),this),L(this,_,this.matchedRoute),R(this,_)&&(R(this,b).value=m.routeView(R(this,_),this.name)),o.watch(this.location.matched,(s,r)=>{const c=r[this.index];c!==R(this,_)&&(L(this,_,c),R(this,b).value=c?m.routeView(c,this.name):void 0)})}get index(){return R(this,P)}get isLastView(){return this.index===this.location.matched.length-1&&this.name==="default"}get name(){return this.props.name||"default"}get matchedRoute(){return this.location.matched[R(this,P)]}get currentElement(){return R(this,b).value}get location(){return m.instance.currentRouteLocation}onMounted(){this.completeViewRender()}onUpdated(){this.completeViewRender()}build(){return this.currentElement||o.createElement(o.Fragment)}completeViewRender(){this.isLastView&&m.instance._completeViewRender()}};E=new WeakMap,P=new WeakMap,_=new WeakMap,b=new WeakMap,x(v,E,Symbol("RouterViewCounter"));let H=v;class dt extends o.Widget{constructor(i){super(i);d(this,"target");d(this,"location");d(this,"active");d(this,"htmlProps");this.target=new o.Computed(()=>o.markRaw(o.isString(i.to)?{index:i.to}:i.to)),this.location=new o.Computed(()=>{const n=m.instance.createRouteLocation(this.target.value);return n.matched.length||console.trace(`[Vitarx.RouterLink][WARN]:索引:${this.target.value.index},未匹配到任何有效的路由线路,请检查to属性是否配置正确!`),o.markRaw(n)}),this.active=new o.Computed(()=>this.location.value.fullPath===m.instance.currentRouteLocation.fullPath),this.htmlProps=new o.Computed(()=>{const n={href:this.href,onClick:s=>this.navigate(s),children:this.children,style:this.props.style,class:this.props.class};return this.isActive&&(n.active=!0),this.isDisabled&&(n.disabled=!0),n})}get isActive(){return this.active.value&&!this.isDisabled}get isDisabled(){return this.props.disabled??!1}get href(){return this.location.value.fullPath}navigate(i){i.stopPropagation(),i.preventDefault(),!this.isDisabled&&m.instance.navigate(this.location.value).then()}build(){return o.createElement("a",this.htmlProps.value)}}a.MemoryRouter=B,a.NavigateStatus=h,a.Router=m,a.RouterLink=dt,a.RouterView=H,a.WebHistoryRouter=F,a.createRouter=ht,a.defineRoute=ct,a.defineRoutes=at,a.lazy=ft,a.useRoute=lt,a.useRouter=ut,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
package/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/vitarx-router.es.js'
|
package/package.json
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitarx-router",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.7",
|
|
4
4
|
"description": "Vitarx前端框架的配套路由器",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/vitarx-router.umd.js",
|
|
7
7
|
"module": "dist/vitarx-router.es.js",
|
|
8
|
-
"types": "dist/vitarx-router.
|
|
8
|
+
"types": "dist/vitarx-router.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"require": {
|
|
12
|
+
"types": "./dist/vitarx-router.d.ts",
|
|
13
|
+
"node": "./dist/vitarx-router.umd.js"
|
|
14
|
+
},
|
|
15
|
+
"import": {
|
|
16
|
+
"types": "./dist/vitarx-router.d.ts",
|
|
17
|
+
"node": "./index.mjs",
|
|
18
|
+
"default": "./dist/vitarx-router.es.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./scripts/make-type": {
|
|
22
|
+
"types": "./dist/scripts/type-make.d.ts",
|
|
23
|
+
"default": "./dist/scripts/type-make.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
9
26
|
"scripts": {
|
|
10
27
|
"dev": "vite --force",
|
|
11
28
|
"tsc:lib": "tsc --p tsconfig-lib.json",
|
|
12
29
|
"vite:lib": "vite --config vite.config.lib.ts build",
|
|
13
|
-
"build:script": "tsc
|
|
30
|
+
"build:script": "tsc --p tsconfig-script.json",
|
|
14
31
|
"build:lib": "rimraf dist && npm run tsc:lib && npm run vite:lib && npm run build:script",
|
|
15
32
|
"build:web": "rimraf dist-web && vite build",
|
|
16
33
|
"preview": "vite preview",
|
|
@@ -18,7 +35,7 @@
|
|
|
18
35
|
"push": "npm publish --access=public"
|
|
19
36
|
},
|
|
20
37
|
"peerDependencies": {
|
|
21
|
-
"vitarx": "^1.0.0-beta.
|
|
38
|
+
"vitarx": "^1.0.0-beta.33"
|
|
22
39
|
},
|
|
23
40
|
"devDependencies": {
|
|
24
41
|
"@types/node": "^22.10.0",
|
|
@@ -31,6 +48,7 @@
|
|
|
31
48
|
"files": [
|
|
32
49
|
"dist",
|
|
33
50
|
"LICENSE",
|
|
34
|
-
"README.md"
|
|
51
|
+
"README.md",
|
|
52
|
+
"index.mjs"
|
|
35
53
|
]
|
|
36
54
|
}
|
|
File without changes
|