跨域问题
wǎng luò shí huāng 2022-01-24
学习es5
跨域
postMessage
document.domain
解决 postMessage 跨域问题、document.domain 跨域及其限制
# 跨域和预检
- https://zhuanlan.zhihu.com/p/53996160
# postMessage 使用场景:
- 从广义上讲,一个窗口可以获得对另一个窗口的引用(比如
targetWindow = window.opener),然后在窗口上调用targetWindow.postMessage()方法分发一个MessageEvent(opens new window) 消息。接收消息的窗口可以根据需要自由处理此事件 (en-US) (opens new window)。传递给 window.postMessage() 的参数(比如 message )将通过消息事件对象暴露给接收消息的窗口 (opens new window):https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的 iframe 消息传递
- 对发送消息的窗口对象的引用; 你可以使用此来在具有不同 origin 的两个窗口之间建立双向通信。
- https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage#source
# 具体使用
# document.domain 跨域
# 订阅发布、 跨 tab 通讯、跨域通讯
class PostMessage {
static targetWindow = window;
// 如果不是跨域通讯,那么connect以及receive方法可以不用调用
static connect(targetWindow) {
// 先打开的页面使用此方法
this.targetWindow = targetWindow ?? this.targetWindow;
if (window.top !== window) {
targetWindow.document.addEventListener("DOMContentLoaded", () => {
this.targetWindow.postMessage({ eventName: "connect" }, "*");
});
}
}
static receive() {
// 后打开的页面调用此方法
window.addEventListener(
"message",
(message) => {
const data = JSON.parse(message.data);
if (data.eventName === "connect") {
this.targetWindow = message.source;
}
},
false
);
}
/**
* @params: {
* eventName: string,
* data: any,
*/
static send(params) {
if (typeof params !== "string") {
params = JSON.stringify(params);
}
this.targetWindow.postMessage(params, this.targetWindow.origin);
}
/**
* @params: {
* eventName: string,
* callback: function
*/
static listen(params) {
window.addEventListener(
"message",
(message) => {
const data = JSON.parse(message.data);
if (data.eventName === params.eventName) {
params.callback?.(data);
}
},
false
);
}
}
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
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
- 已有的库:diy/intercom.js 和 tejacques/crosstab
# 同源 tab 通讯
- const bc1 = new BroadcastChannel("test"); const bc2 = new BroadcastChannel("test"); bc1.postMessage("Hello"); // bc2 会收到此消息 roadcastChannel 通过频道名称(channelName)标识通信通道。无论创建多少个实例,只要使用相同的 channelName,这些实例都会连接到同一个广播频道,实现消息互通。