@esmx/router 3.0.0-rc.18 → 3.0.0-rc.19

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 (158) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +70 -0
  3. package/README.zh-CN.md +70 -0
  4. package/dist/error.d.ts +23 -0
  5. package/dist/error.mjs +61 -0
  6. package/dist/increment-id.d.ts +7 -0
  7. package/dist/increment-id.mjs +11 -0
  8. package/dist/index.d.ts +5 -3
  9. package/dist/index.mjs +14 -3
  10. package/dist/index.test.mjs +8 -0
  11. package/dist/location.d.ts +15 -0
  12. package/dist/location.mjs +53 -0
  13. package/dist/location.test.d.ts +8 -0
  14. package/dist/location.test.mjs +370 -0
  15. package/dist/matcher.d.ts +3 -0
  16. package/dist/matcher.mjs +44 -0
  17. package/dist/matcher.test.mjs +1492 -0
  18. package/dist/micro-app.d.ts +18 -0
  19. package/dist/micro-app.dom.test.d.ts +1 -0
  20. package/dist/micro-app.dom.test.mjs +532 -0
  21. package/dist/micro-app.mjs +80 -0
  22. package/dist/navigation.d.ts +43 -0
  23. package/dist/navigation.mjs +143 -0
  24. package/dist/navigation.test.d.ts +1 -0
  25. package/dist/navigation.test.mjs +681 -0
  26. package/dist/options.d.ts +4 -0
  27. package/dist/options.mjs +88 -0
  28. package/dist/route-task.d.ts +40 -0
  29. package/dist/route-task.mjs +75 -0
  30. package/dist/route-task.test.d.ts +1 -0
  31. package/dist/route-task.test.mjs +673 -0
  32. package/dist/route-transition.d.ts +53 -0
  33. package/dist/route-transition.mjs +307 -0
  34. package/dist/route-transition.test.d.ts +1 -0
  35. package/dist/route-transition.test.mjs +146 -0
  36. package/dist/route.d.ts +72 -0
  37. package/dist/route.mjs +194 -0
  38. package/dist/route.test.d.ts +1 -0
  39. package/dist/route.test.mjs +1664 -0
  40. package/dist/router-back.test.d.ts +1 -0
  41. package/dist/router-back.test.mjs +361 -0
  42. package/dist/router-forward.test.d.ts +1 -0
  43. package/dist/router-forward.test.mjs +376 -0
  44. package/dist/router-go.test.d.ts +1 -0
  45. package/dist/router-go.test.mjs +73 -0
  46. package/dist/router-guards-cleanup.test.d.ts +1 -0
  47. package/dist/router-guards-cleanup.test.mjs +437 -0
  48. package/dist/router-link.d.ts +10 -0
  49. package/dist/router-link.mjs +126 -0
  50. package/dist/router-push.test.d.ts +1 -0
  51. package/dist/router-push.test.mjs +115 -0
  52. package/dist/router-replace.test.d.ts +1 -0
  53. package/dist/router-replace.test.mjs +114 -0
  54. package/dist/router-resolve.test.d.ts +1 -0
  55. package/dist/router-resolve.test.mjs +393 -0
  56. package/dist/router-restart-app.dom.test.d.ts +1 -0
  57. package/dist/router-restart-app.dom.test.mjs +616 -0
  58. package/dist/router-window-navigation.test.d.ts +1 -0
  59. package/dist/router-window-navigation.test.mjs +359 -0
  60. package/dist/router.d.ts +109 -102
  61. package/dist/router.mjs +260 -361
  62. package/dist/types.d.ts +246 -0
  63. package/dist/types.mjs +18 -0
  64. package/dist/util.d.ts +26 -0
  65. package/dist/util.mjs +53 -0
  66. package/dist/util.test.d.ts +1 -0
  67. package/dist/util.test.mjs +1020 -0
  68. package/package.json +10 -13
  69. package/src/error.ts +84 -0
  70. package/src/increment-id.ts +12 -0
  71. package/src/index.test.ts +9 -0
  72. package/src/index.ts +54 -3
  73. package/src/location.test.ts +406 -0
  74. package/src/location.ts +96 -0
  75. package/src/matcher.test.ts +1685 -0
  76. package/src/matcher.ts +59 -0
  77. package/src/micro-app.dom.test.ts +708 -0
  78. package/src/micro-app.ts +101 -0
  79. package/src/navigation.test.ts +858 -0
  80. package/src/navigation.ts +195 -0
  81. package/src/options.ts +131 -0
  82. package/src/route-task.test.ts +901 -0
  83. package/src/route-task.ts +105 -0
  84. package/src/route-transition.test.ts +178 -0
  85. package/src/route-transition.ts +425 -0
  86. package/src/route.test.ts +2014 -0
  87. package/src/route.ts +308 -0
  88. package/src/router-back.test.ts +487 -0
  89. package/src/router-forward.test.ts +506 -0
  90. package/src/router-go.test.ts +91 -0
  91. package/src/router-guards-cleanup.test.ts +595 -0
  92. package/src/router-link.ts +235 -0
  93. package/src/router-push.test.ts +140 -0
  94. package/src/router-replace.test.ts +139 -0
  95. package/src/router-resolve.test.ts +475 -0
  96. package/src/router-restart-app.dom.test.ts +783 -0
  97. package/src/router-window-navigation.test.ts +457 -0
  98. package/src/router.ts +289 -470
  99. package/src/types.ts +341 -0
  100. package/src/util.test.ts +1262 -0
  101. package/src/util.ts +116 -0
  102. package/dist/history/abstract.d.ts +0 -29
  103. package/dist/history/abstract.mjs +0 -107
  104. package/dist/history/base.d.ts +0 -79
  105. package/dist/history/base.mjs +0 -275
  106. package/dist/history/html.d.ts +0 -30
  107. package/dist/history/html.mjs +0 -183
  108. package/dist/history/index.d.ts +0 -7
  109. package/dist/history/index.mjs +0 -16
  110. package/dist/matcher/create-matcher.d.ts +0 -5
  111. package/dist/matcher/create-matcher.mjs +0 -218
  112. package/dist/matcher/create-matcher.spec.mjs +0 -0
  113. package/dist/matcher/index.d.ts +0 -1
  114. package/dist/matcher/index.mjs +0 -1
  115. package/dist/task-pipe/index.d.ts +0 -1
  116. package/dist/task-pipe/index.mjs +0 -1
  117. package/dist/task-pipe/task.d.ts +0 -30
  118. package/dist/task-pipe/task.mjs +0 -66
  119. package/dist/types/index.d.ts +0 -694
  120. package/dist/types/index.mjs +0 -6
  121. package/dist/utils/bom.d.ts +0 -5
  122. package/dist/utils/bom.mjs +0 -10
  123. package/dist/utils/encoding.d.ts +0 -48
  124. package/dist/utils/encoding.mjs +0 -44
  125. package/dist/utils/guards.d.ts +0 -9
  126. package/dist/utils/guards.mjs +0 -12
  127. package/dist/utils/index.d.ts +0 -7
  128. package/dist/utils/index.mjs +0 -27
  129. package/dist/utils/path.d.ts +0 -60
  130. package/dist/utils/path.mjs +0 -282
  131. package/dist/utils/path.spec.mjs +0 -27
  132. package/dist/utils/scroll.d.ts +0 -25
  133. package/dist/utils/scroll.mjs +0 -59
  134. package/dist/utils/utils.d.ts +0 -16
  135. package/dist/utils/utils.mjs +0 -11
  136. package/dist/utils/warn.d.ts +0 -2
  137. package/dist/utils/warn.mjs +0 -12
  138. package/src/history/abstract.ts +0 -149
  139. package/src/history/base.ts +0 -408
  140. package/src/history/html.ts +0 -228
  141. package/src/history/index.ts +0 -20
  142. package/src/matcher/create-matcher.spec.ts +0 -3
  143. package/src/matcher/create-matcher.ts +0 -292
  144. package/src/matcher/index.ts +0 -1
  145. package/src/task-pipe/index.ts +0 -1
  146. package/src/task-pipe/task.ts +0 -97
  147. package/src/types/index.ts +0 -858
  148. package/src/utils/bom.ts +0 -14
  149. package/src/utils/encoding.ts +0 -153
  150. package/src/utils/guards.ts +0 -25
  151. package/src/utils/index.ts +0 -27
  152. package/src/utils/path.spec.ts +0 -32
  153. package/src/utils/path.ts +0 -418
  154. package/src/utils/scroll.ts +0 -120
  155. package/src/utils/utils.ts +0 -30
  156. package/src/utils/warn.ts +0 -13
  157. /package/dist/{matcher/create-matcher.spec.d.ts → index.test.d.ts} +0 -0
  158. /package/dist/{utils/path.spec.d.ts → matcher.test.d.ts} +0 -0
package/src/util.ts ADDED
@@ -0,0 +1,116 @@
1
+ import type { Route, RouteConfirmHookResult, RouteMatchType } from './types';
2
+ export const isBrowser = typeof window === 'object';
3
+
4
+ export function isNotNullish(value: unknown): boolean {
5
+ return (
6
+ value !== undefined &&
7
+ value !== null &&
8
+ !Number.isNaN(
9
+ value instanceof Number
10
+ ? value.valueOf() // For new Number() cases
11
+ : value
12
+ )
13
+ );
14
+ }
15
+
16
+ export function isPlainObject(o: unknown): o is Record<string, any> {
17
+ return (
18
+ o?.constructor === Object ||
19
+ Object.prototype.toString.call(o) === '[object Object]'
20
+ );
21
+ }
22
+
23
+ /**
24
+ * Check if value is a valid non-empty plain object
25
+ * Only check enumerable string keys to ensure it's a proper plain object
26
+ * @param value Value to check
27
+ * @returns true if it's a valid non-empty plain object
28
+ */
29
+ export function isNonEmptyPlainObject(
30
+ value: unknown
31
+ ): value is Record<string, any> {
32
+ if (!isPlainObject(value)) {
33
+ return false;
34
+ }
35
+ // Only check enumerable string keys to ensure valid properties of plain object
36
+ return Object.keys(value as Record<string, any>).length > 0;
37
+ }
38
+
39
+ export const removeFromArray = <T>(arr: T[], ele: T) => {
40
+ if (!Array.isArray(arr) || arr.length === 0) return;
41
+ const i = Number.isNaN(ele)
42
+ ? // If ele is NaN, use findIndex to search for NaN, because NaN !== NaN, so we can't use indexOf directly
43
+ arr.findIndex((item) => Number.isNaN(item))
44
+ : arr.indexOf(ele);
45
+ if (i === -1) return;
46
+ arr.splice(i, 1);
47
+ };
48
+
49
+ export function isValidConfirmHookResult(
50
+ result: unknown
51
+ ): result is Exclude<RouteConfirmHookResult, void> {
52
+ return (
53
+ result === false ||
54
+ typeof result === 'function' ||
55
+ typeof result === 'string' ||
56
+ isPlainObject(result)
57
+ );
58
+ }
59
+
60
+ export function isUrlEqual(url1: URL, url2?: URL | null): boolean {
61
+ // If url2 doesn't exist, return false
62
+ if (!url2) {
63
+ return false;
64
+ }
65
+
66
+ // If it's the same object reference, return true directly
67
+ if (url1 === url2) {
68
+ return true;
69
+ }
70
+
71
+ // Copy and sort query parameters
72
+ (url1 = new URL(url1)).searchParams.sort();
73
+ (url2 = new URL(url2)).searchParams.sort();
74
+ // Avoid trailing hash symbol impact from empty hash
75
+ // biome-ignore lint/correctness/noSelfAssign:
76
+ url1.hash = url1.hash;
77
+ // biome-ignore lint/correctness/noSelfAssign:
78
+ url2.hash = url2.hash;
79
+ return url1.href === url2.href;
80
+ }
81
+
82
+ /**
83
+ * Compare if two routes match
84
+ *
85
+ * @param route1 First route object
86
+ * @param route2 Second route object, may be null
87
+ * @param matchType Match type
88
+ * - 'route': Route-level matching, compare if route configurations are the same
89
+ * - 'exact': Exact matching, compare if full paths are the same
90
+ * - 'include': Include matching, check if route1 path starts with route2 path
91
+ * @returns Whether they match
92
+ */
93
+ export function isRouteMatched(
94
+ route1: Route,
95
+ route2: Route | null,
96
+ matchType: RouteMatchType
97
+ ): boolean {
98
+ if (!route2) return false;
99
+
100
+ switch (matchType) {
101
+ case 'route':
102
+ // Route-level matching - compare route configurations
103
+ return route1.config === route2.config;
104
+
105
+ case 'exact':
106
+ // Exact matching - full paths are identical
107
+ return route1.fullPath === route2.fullPath;
108
+
109
+ case 'include':
110
+ // Include matching - route1 path contains route2 path
111
+ return route1.fullPath.startsWith(route2.fullPath);
112
+
113
+ default:
114
+ return false;
115
+ }
116
+ }
@@ -1,29 +0,0 @@
1
- import type { Route, RouteRecord, RouterInstance, RouterRawLocation } from '../types';
2
- import { BaseRouterHistory } from './base';
3
- export declare class AbstractHistory extends BaseRouterHistory {
4
- index: number;
5
- stack: RouteRecord[];
6
- constructor(router: RouterInstance);
7
- init({ replace }?: {
8
- replace?: boolean;
9
- }): Promise<void>;
10
- destroy(): void;
11
- setupListeners(): void;
12
- isSameHost(location: RouterRawLocation, route: Route): boolean;
13
- handleOutside(location: RouterRawLocation, replace?: boolean, isTriggerWithWindow?: boolean): boolean;
14
- push(location: RouterRawLocation): Promise<void>;
15
- /**
16
- * 新开浏览器窗口的方法,在服务端会调用 push 作为替代
17
- */
18
- pushWindow(location: RouterRawLocation): Promise<void>;
19
- replace(location: RouterRawLocation): Promise<void>;
20
- /**
21
- * 替换当前浏览器窗口的方法,在服务端会调用 replace 作为替代
22
- */
23
- replaceWindow(location: RouterRawLocation): Promise<void>;
24
- jump(location: RouterRawLocation, replace?: boolean): Promise<void>;
25
- _jump(location: RouterRawLocation, replace?: boolean, isTriggerWithWindow?: boolean): Promise<void>;
26
- go(delta: number): void;
27
- forward(): void;
28
- back(): void;
29
- }
@@ -1,107 +0,0 @@
1
- import { isPathWithProtocolOrDomain, normalizeLocation } from "../utils/index.mjs";
2
- import { BaseRouterHistory } from "./base.mjs";
3
- export class AbstractHistory extends BaseRouterHistory {
4
- index;
5
- stack;
6
- constructor(router) {
7
- super(router);
8
- this.index = -1;
9
- this.stack = [];
10
- }
11
- async init({ replace } = { replace: true }) {
12
- const { initUrl } = this.router.options;
13
- if (initUrl !== void 0) {
14
- if (replace) {
15
- await this.replace(initUrl);
16
- } else {
17
- await this.push(initUrl);
18
- }
19
- }
20
- }
21
- destroy() {
22
- }
23
- // 设置监听函数
24
- setupListeners() {
25
- }
26
- // 服务端判断是否是相同域名
27
- isSameHost(location, route) {
28
- const rawLocation = typeof location === "string" ? { path: location } : location;
29
- if (rawLocation.path === void 0) {
30
- rawLocation.path = this.current.fullPath;
31
- }
32
- const { base } = normalizeLocation(rawLocation, this.router.base);
33
- return base.includes(route.hostname);
34
- }
35
- // 处理外站跳转逻辑
36
- handleOutside(location, replace = false, isTriggerWithWindow = false) {
37
- const base = this.router.base;
38
- const { flag, route } = isPathWithProtocolOrDomain(location, base);
39
- if (!flag) {
40
- return false;
41
- }
42
- const router = this.router;
43
- const { validateOutside, handleOutside } = router.options;
44
- const isSameHost = this.isSameHost(location, route);
45
- if (isSameHost && !(validateOutside == null ? void 0 : validateOutside({ router, location, route }))) {
46
- return false;
47
- }
48
- handleOutside == null ? void 0 : handleOutside({
49
- router,
50
- route,
51
- replace,
52
- isTriggerWithWindow,
53
- isSameHost
54
- });
55
- return true;
56
- }
57
- // 新增路由记录跳转
58
- async push(location) {
59
- await this.jump(location, false);
60
- }
61
- /**
62
- * 新开浏览器窗口的方法,在服务端会调用 push 作为替代
63
- */
64
- async pushWindow(location) {
65
- await this._jump(location, false, true);
66
- }
67
- // 替换当前路由记录跳转
68
- async replace(location) {
69
- await this.jump(location, true);
70
- }
71
- /**
72
- * 替换当前浏览器窗口的方法,在服务端会调用 replace 作为替代
73
- */
74
- async replaceWindow(location) {
75
- await this._jump(location, true, true);
76
- }
77
- // 跳转方法
78
- async jump(location, replace = false) {
79
- await this._jump(location, replace);
80
- }
81
- async _jump(location, replace = false, isTriggerWithWindow = false) {
82
- if (this.handleOutside(location, replace, isTriggerWithWindow)) {
83
- return;
84
- }
85
- await this.transitionTo(location, (route) => {
86
- const index = replace ? this.index : this.index + 1;
87
- this.stack = this.stack.slice(0, index).concat(route);
88
- });
89
- }
90
- go(delta) {
91
- const targetIndex = this.index + delta;
92
- if (targetIndex < 0 || targetIndex >= this.stack.length) {
93
- return;
94
- }
95
- const route = this.stack[targetIndex];
96
- this.index = targetIndex;
97
- this.updateRoute(route);
98
- }
99
- /* 路由历史记录前进方法 */
100
- forward() {
101
- this.go(1);
102
- }
103
- /* 路由历史记录后退方法 */
104
- back() {
105
- this.go(-1);
106
- }
107
- }
@@ -1,79 +0,0 @@
1
- import { type Tasks } from '../task-pipe';
2
- import type { RouteRecord, RouterHistory, RouterInstance, RouterRawLocation } from '../types';
3
- export declare abstract class BaseRouterHistory implements RouterHistory {
4
- /**
5
- * 路由类实例
6
- */
7
- router: RouterInstance;
8
- /**
9
- * 路由是否冻结
10
- */
11
- get isFrozen(): boolean;
12
- /**
13
- * 匹配的当前路由
14
- */
15
- current: RouteRecord;
16
- constructor(router: RouterInstance);
17
- /**
18
- * 更新当前路由
19
- */
20
- updateRoute(route: RouteRecord): void;
21
- /**
22
- * 解析路由
23
- */
24
- resolve(location: RouterRawLocation): RouteRecord;
25
- /**
26
- * 核心跳转方法
27
- */
28
- transitionTo(location: RouterRawLocation, onComplete?: (route: RouteRecord) => void): Promise<void>;
29
- /**
30
- * TODO 逻辑解耦,抽离到task
31
- * 重定向方法
32
- */
33
- redirectTo(location: RouterRawLocation, from: RouteRecord, onComplete?: (route: RouteRecord) => void): Promise<void>;
34
- tasks: Tasks | null;
35
- abortTask(): Promise<void>;
36
- /**
37
- * 执行任务
38
- * 任务分为三部分: 前置守卫(beforeEach、beforeEnter、beforeUpdate、beforeLeave)、加载路由(loadRoute)、后置守卫(afterEach)
39
- * 根据触发方式不同,执行顺序分别为:
40
- * 进入路由时: beforeEach -> beforeEnter -> loadRoute -> afterEach
41
- * 更新路由时: beforeEach -> beforeUpdate -> afterEach
42
- * 离开路由进入新路由时: beforeLeave -> beforeEach -> beforeEnter -> loadRoute -> afterEach
43
- * @param from
44
- * @param to
45
- */
46
- runTask(from: RouteRecord, to: RouteRecord, onComplete?: (route: RouteRecord) => void): Promise<void>;
47
- /**
48
- * 新开浏览器窗口的方法,在服务端会调用 push 作为替代
49
- */
50
- abstract pushWindow(location: RouterRawLocation): void;
51
- /**
52
- * 替换当前浏览器窗口的方法,在服务端会调用 replace 作为替代
53
- */
54
- abstract replaceWindow(location: RouterRawLocation): void;
55
- /**
56
- * 跳转方法,会创建新的历史纪录
57
- */
58
- abstract push(location: RouterRawLocation): Promise<void>;
59
- /**
60
- * 跳转方法,替换当前历史记录
61
- */
62
- abstract replace(location: RouterRawLocation): Promise<void>;
63
- /**
64
- * 路由移动到指定历史记录方法
65
- */
66
- abstract go(delta: number): void;
67
- abstract forward(): void;
68
- abstract back(): void;
69
- /**
70
- * 初始化方法
71
- */
72
- abstract init(params?: {
73
- replace?: boolean;
74
- }): Promise<void>;
75
- /**
76
- * 卸载方法
77
- */
78
- abstract destroy(): void;
79
- }
@@ -1,275 +0,0 @@
1
- import { createTasks } from "../task-pipe/index.mjs";
2
- import {
3
- isESModule,
4
- isEqualRoute,
5
- isSameRoute,
6
- normalizeLocation,
7
- stringifyPath
8
- } from "../utils/index.mjs";
9
- function createRouteRecord(route = {}) {
10
- return {
11
- base: "",
12
- path: "/",
13
- fullPath: "/",
14
- meta: {},
15
- matched: [],
16
- query: {},
17
- queryArray: {},
18
- params: {},
19
- hash: "",
20
- state: {},
21
- ...route
22
- };
23
- }
24
- export class BaseRouterHistory {
25
- /**
26
- * 路由类实例
27
- */
28
- router;
29
- /**
30
- * 路由是否冻结
31
- */
32
- get isFrozen() {
33
- return this.router.isFrozen;
34
- }
35
- /**
36
- * 匹配的当前路由
37
- */
38
- current = createRouteRecord();
39
- constructor(router) {
40
- this.router = router;
41
- Object.defineProperty(this, "router", {
42
- enumerable: false
43
- });
44
- }
45
- /**
46
- * 更新当前路由
47
- */
48
- updateRoute(route) {
49
- this.current = route;
50
- this.router.updateRoute(route);
51
- }
52
- /**
53
- * 解析路由
54
- */
55
- resolve(location) {
56
- const rawLocation = typeof location === "string" ? { path: location } : location;
57
- if (rawLocation.path === void 0) {
58
- rawLocation.path = this.current.fullPath;
59
- }
60
- const { base, ...normalizedLocation } = normalizeLocation(
61
- rawLocation,
62
- this.router.base
63
- );
64
- const matcher = this.router.matcher.match(normalizedLocation, { base });
65
- if (matcher) {
66
- return matcher;
67
- }
68
- const {
69
- path = "",
70
- params = {},
71
- query = {},
72
- queryArray = {},
73
- hash = "",
74
- state = {}
75
- } = normalizedLocation;
76
- const route = createRouteRecord({
77
- base,
78
- fullPath: stringifyPath({
79
- pathname: path,
80
- query,
81
- queryArray,
82
- hash
83
- }),
84
- path,
85
- params,
86
- query,
87
- queryArray,
88
- hash,
89
- state
90
- });
91
- return route;
92
- }
93
- /**
94
- * 核心跳转方法
95
- */
96
- async transitionTo(location, onComplete) {
97
- if (this.isFrozen) return;
98
- const route = this.resolve(location);
99
- this.abortTask();
100
- if (isEqualRoute(this.current, route)) {
101
- return;
102
- }
103
- await this.runTask(this.current, route, onComplete);
104
- }
105
- /**
106
- * TODO 逻辑解耦,抽离到task
107
- * 重定向方法
108
- */
109
- async redirectTo(location, from, onComplete) {
110
- const route = this.resolve(location);
111
- this.abortTask();
112
- if (isEqualRoute(this.current, route)) {
113
- return;
114
- }
115
- await this.runTask(
116
- this.current,
117
- {
118
- ...route,
119
- redirectedFrom: from
120
- },
121
- onComplete
122
- );
123
- }
124
- /* 当前执行的任务 */
125
- tasks = null;
126
- /* 取消任务 */
127
- async abortTask() {
128
- var _a;
129
- (_a = this.tasks) == null ? void 0 : _a.abort();
130
- }
131
- /**
132
- * 执行任务
133
- * 任务分为三部分: 前置守卫(beforeEach、beforeEnter、beforeUpdate、beforeLeave)、加载路由(loadRoute)、后置守卫(afterEach)
134
- * 根据触发方式不同,执行顺序分别为:
135
- * 进入路由时: beforeEach -> beforeEnter -> loadRoute -> afterEach
136
- * 更新路由时: beforeEach -> beforeUpdate -> afterEach
137
- * 离开路由进入新路由时: beforeLeave -> beforeEach -> beforeEnter -> loadRoute -> afterEach
138
- * @param from
139
- * @param to
140
- */
141
- async runTask(from, to, onComplete) {
142
- var _a;
143
- const {
144
- beforeEach,
145
- beforeEnter,
146
- beforeUpdate,
147
- beforeLeave,
148
- afterEach,
149
- loadRoute
150
- } = getNavigationHooks(this.router, from, to);
151
- const guardBeforeTasks = createTasks();
152
- const guardAfterTasks = createTasks();
153
- const loadRouteTasks = createTasks();
154
- if (isSameRoute(from, to)) {
155
- guardBeforeTasks.add([...beforeEach, ...beforeUpdate]);
156
- guardAfterTasks.add(afterEach);
157
- } else {
158
- guardBeforeTasks.add([
159
- ...beforeLeave,
160
- ...beforeEach,
161
- ...beforeEnter
162
- ]);
163
- loadRouteTasks.add(loadRoute);
164
- guardAfterTasks.add(afterEach);
165
- }
166
- this.tasks = guardBeforeTasks;
167
- await guardBeforeTasks.run({
168
- cb: async (res) => {
169
- var _a2;
170
- switch (typeof res) {
171
- case "boolean":
172
- if (!res) {
173
- (_a2 = this.tasks) == null ? void 0 : _a2.abort();
174
- }
175
- break;
176
- case "undefined":
177
- break;
178
- default:
179
- await this.redirectTo(res, from, onComplete);
180
- break;
181
- }
182
- },
183
- final: async () => {
184
- this.tasks = loadRouteTasks;
185
- await loadRouteTasks.run();
186
- }
187
- });
188
- if (((_a = this.tasks) == null ? void 0 : _a.status) === "finished") {
189
- this.tasks = null;
190
- guardAfterTasks.run();
191
- onComplete && onComplete(to);
192
- this.updateRoute(to);
193
- }
194
- }
195
- }
196
- function getNavigationHooks(router, from, to) {
197
- const beforeEach = router.guards.beforeEach.map((guard) => {
198
- return () => {
199
- return guard(from, to);
200
- };
201
- });
202
- const afterEach = router.guards.afterEach.map((guard) => {
203
- return () => {
204
- return guard(from, to);
205
- };
206
- });
207
- const { beforeLeave } = from.matched.reduce(
208
- (acc, { beforeLeave: beforeLeave2 }) => {
209
- if (beforeLeave2) {
210
- acc.beforeLeave.unshift(() => {
211
- return beforeLeave2(from, to);
212
- });
213
- }
214
- return acc;
215
- },
216
- {
217
- beforeLeave: []
218
- }
219
- );
220
- const { beforeEnter, beforeUpdate } = to.matched.reduce(
221
- (acc, { beforeEnter: beforeEnter2, beforeUpdate: beforeUpdate2 }) => {
222
- if (beforeEnter2) {
223
- acc.beforeEnter.push(() => {
224
- return beforeEnter2(from, to);
225
- });
226
- }
227
- if (beforeUpdate2) {
228
- acc.beforeUpdate.push(() => {
229
- return beforeUpdate2(from, to);
230
- });
231
- }
232
- return acc;
233
- },
234
- {
235
- beforeEnter: [],
236
- beforeUpdate: []
237
- }
238
- );
239
- const loadRoute = [
240
- async () => {
241
- return Promise.all(
242
- to.matched.reduce((acc, route) => {
243
- if (!route.component && route.asyncComponent) {
244
- acc.push(
245
- new Promise((resolve, reject) => {
246
- if (!route.component && route.asyncComponent) {
247
- route.asyncComponent().then((resolved) => {
248
- if (!resolved) {
249
- reject(
250
- new Error(
251
- `Couldn't resolve component at "${route.path}". Ensure you passed a function that returns a promise.`
252
- )
253
- );
254
- }
255
- route.component = isESModule(resolved) ? resolved.default : resolved;
256
- resolve();
257
- });
258
- }
259
- })
260
- );
261
- }
262
- return acc;
263
- }, [])
264
- );
265
- }
266
- ];
267
- return {
268
- beforeEach,
269
- afterEach,
270
- beforeEnter,
271
- beforeUpdate,
272
- beforeLeave,
273
- loadRoute
274
- };
275
- }
@@ -1,30 +0,0 @@
1
- import type { RouterInstance, RouterRawLocation } from '../types';
2
- import { BaseRouterHistory } from './base';
3
- export declare class HtmlHistory extends BaseRouterHistory {
4
- constructor(router: RouterInstance);
5
- getCurrentLocation(): {
6
- state: any;
7
- query?: Record<string, string | undefined>;
8
- queryArray: Record<string, string[]>;
9
- params?: Record<string, string>;
10
- hash?: string;
11
- path: string;
12
- base: string;
13
- };
14
- onPopState: (e: PopStateEvent) => void;
15
- init({ replace }?: {
16
- replace?: boolean;
17
- }): Promise<void>;
18
- setupListeners(): void;
19
- destroy(): void;
20
- pushWindow(location: RouterRawLocation): void;
21
- replaceWindow(location: RouterRawLocation): void;
22
- handleOutside(location: RouterRawLocation, replace?: boolean, isTriggerWithWindow?: boolean): boolean;
23
- push(location: RouterRawLocation): Promise<void>;
24
- replace(location: RouterRawLocation): Promise<void>;
25
- jump(location: RouterRawLocation, replace?: boolean): Promise<void>;
26
- go(delta: number): void;
27
- forward(): void;
28
- protected timer: NodeJS.Timeout | null;
29
- back(): void;
30
- }