Appearance
路由劫持 #
为了保证应用加载逻辑最先被处理,我们对路由的一系列的方法进行重写,确保加载应用的逻辑最先被调用,其次手动派发事件
目录 #
bash
├── navigations
│ ├── navigation-events.js
│ └── reroute.js
1
2
3
2
3
代码 #
javascript
import { reroute } from "./reroute";
// 用户可能还会绑定自己的路由事件 vue
// 当我们应用切换后,还需要处理原来的方法,需要再应用切换后在执行
export const routingEventsListeningTo = ["hashchange", "popstate"];
function urlReroute() {
reroute([], arguments); // 会更新路径重新加载不同的应用
}
// 后续挂载的时间先暂存起来
const capturedEventListeners = {
hashChange: [],
popstate: [],
};
// hash 方法实现
// 劫持路由变化,我们处理应用加载的逻辑是在最前面
window.addEventListener("hashchange", urlReroute);
window.addEventListener("popstate", urlReroute);
// 重写addEventListener方法
const originalAddEventListener = window.addEventListener;
const originalRemoveEventListener = window.removeEventListener;
window.addEventListener = function (eventName, fn) {
if (
routingEventsListeningTo.indexOf(eventName) >= 0 &&
!capturedEventListeners[eventName].some((listener) => listener == fn)
) {
capturedEevntListeners[eventName].push(fn);
return;
}
return originalAddEventListener.apply(this, arguments);
};
window.removeEventListener = function (eventName, listenerFn) {
if (routingEventsListeningTo.indexOf(eventName) >= 0) {
capturedEventListeners[eventName] = capturedEventListeners[
eventName
].filter((fn) => fn !== listenerFn);
return;
}
return originalRemoveEventListener.apply(this, arguments);
};
// 如果是hash路由 hash变化时可以切换
// 浏览器路由,浏览器路由是h5api的 如果切换时不会触发popstate
// patched
function patchedUpdateState(updateState, methodName) {
return function () {
const urlBefore = window.location.href;
const result = updateState.apply(this, arguments);
const urlAfter = window.location.href;
if (urlBefore !== urlAfter) {
urlReroute(new PopStateEvent("popstate", { state }));
}
return result;
};
}
// 重写pushState 和 repalceState方法
window.history.pushState = patchedUpdateState(
window.history.pushState,
"pushState"
);
window.history.replaceState = patchedUpdateState(
window.history.replaceState,
"replaceState"
);
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
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
加载应用 #
javascript
await Promise.all(appsToLoad.map(toLoadPromise)); // 加载后触发路由方法
callCapturedEventListeners(eventArguments);
await Promise.all(unmountPromises); // 等待先卸载完成后触发路由方法
callCapturedEventListeners(eventArguments);
1
2
3
4
5
6
2
3
4
5
6
校验当前是否需要被激活,在进行启动和挂载
javascript
async function tryToBootstrapAndMount(app) {
if (shouldBeActive(app)) {
app = await toBootstrapPromise(app);
return toMountPromise(app);
}
return app;
}
1
2
3
4
5
6
7
2
3
4
5
6
7