在iframe里面使用react-router

说明

iframe 里面嵌入一个基于 HTML5 history 的现代网站,如果需要调用最顶层的浏览器路由(即路由地址体现在地址栏,而不是在 iframe 内的沙箱中)

那么该嵌入的代码就需要添加如下逻辑,去调用父容器的浏览器地址逻辑,这样页面的路由切换也将在浏览器的地址栏有所展示

否则,在 iframe 嵌入单页应用的页面时,在单页路由切换时,浏览器的地址栏不会发生任何变化,会导致页面刷新后,无法正常定位网页内容

实现代码

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
import { history as RouterHistory } from "award-router";
import { createLocation } from "history";

function hasBasename(path, prefix) {
return (
path.toLowerCase().indexOf(prefix.toLowerCase()) === 0 &&
"/?#".indexOf(path.charAt(prefix.length)) !== -1
);
}

function stripBasename(path, prefix) {
return hasBasename(path, prefix) ? path.substr(prefix.length) : path;
}

/**
* 路由系统全部交给parent管理
*/
let parentHistory = window.parent.history;
let localReplaceState = history.replaceState;
history.pushState = function () {
// console.log('pushState', arguments);
if (arguments[0] && arguments[0].state === "null") {
return;
}
parentHistory.pushState.apply(parentHistory, arguments);
localReplaceState.apply(history, arguments);
};
history.replaceState = function () {
// console.log('replaceState', arguments);
parentHistory.replaceState.apply(parentHistory, arguments);
localReplaceState.apply(history, arguments);
};
window.parent.addEventListener("popstate", function (e) {
// 这里其实路由已经发生变化了,只是react-router的组件没有按照正确的渲染,这里就是要让他进行渲染
let _ref = e.state || {};
let key = _ref.key;
let state = _ref.state;

let _window$location = window.parent.location;
let pathname = _window$location.pathname;
let search = _window$location.search;
let hash = _window$location.hash;
let path = pathname + search + hash;
path = stripBasename(path, "/gatekeeper/lego");
const location = createLocation(path, state, key);
localReplaceState.apply(history, [
"",
"",
location.pathname + location.search,
]);
RouterHistory.push({
pathname: location.pathname,
search: location.search,
state: "null",
});
});