-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.ts
73 lines (59 loc) · 1.59 KB
/
router.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { makeMap, isUndef, Ctor, MapHas } from "suika";
import { NotFound } from "./NotFound";
import { navigate, pathToRegex } from "./utils";
export type RouterOptions = {
routes: Route[];
mode: string;
};
export interface Route {
component: Ctor;
path: string;
regex?: RegExp;
}
const modes: MapHas = makeMap("history,pushstate");
export class Router {
routes: Route[];
mode: string;
current: string;
constructor(options: RouterOptions) {
this.routes = options.routes;
this.mode = options.mode || "hash";
this.current = this.getFragment();
}
public getFragment(): string {
let fragment = "";
if (this.mode === "history") {
fragment = decodeURI(window.location.pathname + window.location.search);
fragment = fragment.replace(/\?(.*)$/, "");
} else {
const match = window.location.href.match(/#(.*)$/);
fragment = match ? match[1] : "/";
}
return fragment;
}
public getHandler(path = ""): Ctor {
const result = this.routes.find((route: Route) => {
return route.regex?.test(path);
});
if (result && result.component) {
return result.component;
} else {
return NotFound;
}
}
public navigate(path = "") {
navigate(path, this.mode);
}
}
export const createRouter = (options: RouterOptions) => {
if (isUndef(options.mode) || !modes(options.mode)) {
options.mode = "hash";
}
if (Array.isArray(options.routes)) {
options.routes = options.routes.map((route: Route) => {
route.regex = pathToRegex(route.path);
return route;
});
}
return new Router(options);
};