Skip to content
On this page

路由劫持

为了保证应用加载逻辑最先被处理,我们对路由的一系列的方法进行重写,确保加载应用的逻辑最先被调用,其次手动派发事件

目录

bash
   ├── navigations
   │   ├── navigation-events.js
   │   └── reroute.js
1
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

加载应用

javascript
await Promise.all(appsToLoad.map(toLoadPromise)); // 加载后触发路由方法
callCapturedEventListeners(eventArguments);


await Promise.all(unmountPromises); // 等待先卸载完成后触发路由方法
callCapturedEventListeners(eventArguments);
1
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
沪ICP备20006251号-1