Skip to content

Commit c9eee23

Browse files
committed
docs: add window.postMessage()
1 parent d27b94c commit c9eee23

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

chapters.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@
1919
- urlsearchparams.md: URLSearchParams 对象
2020
- websocket.md: WebSocket
2121
- web-share-api.md: Web Share API
22+
- postmessage.md: window.postMessage() 方法

docs/postmessage.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# window.postMessage() 方法
2+
3+
## 简介
4+
5+
`window.postMessage()`用于浏览器不同窗口之间的通信,主要包括 iframe 嵌入窗口和新开窗口两种情况。它不要求两个窗口同源,所以有着广泛的应用。
6+
7+
`window.postMessage()`里面的`window`对象,是发送消息的目标窗口。比如,父窗口通过`window.open()`打开子窗口,那么子窗口可以通过`targetWindow = window.opener`获取父窗口。再比如,父窗口通过`iframe`嵌入了子窗口,那么子窗口可以通过`window.parent`获取父窗口。
8+
9+
## 参数和返回值
10+
11+
`window.postMessage()`方法有几种使用形式。
12+
13+
最简单的一种就是直接发送消息。
14+
15+
```javascript
16+
window.postMessage(message)
17+
```
18+
19+
上面写法中的`message`就是发送的消息,可以是字符串,也可以是对象。如果是对象,浏览器会自动将该对象序列化,以字符串形式发送。
20+
21+
由于`window.postMessage()`可以用于任意两个源(协议+域名+端口)之间的通信,为了减少安全隐患,可以使用第二个参数`targetOrigin`,指定目标窗口的源。
22+
23+
```javascript
24+
window.postMessage(message, targetOrigin)
25+
```
26+
27+
上面写法中的`targetOrigin`是一个字符串,表示目标窗口里面的网页的源(origin),比如`https://example.com`。如果对目标窗口不加限制,可以省略这个参数,或者写成`*`。一旦指定了该参数,只有目标窗口符合指定的源(协议+域名+端口),目标窗口才会接收到消息发送事件。
28+
29+
`window.postMessage()`还可以指定第三个参数,用于发送一些可传送物体(transferable object),比如 ArrayBuffer 对象。
30+
31+
```javascript
32+
window.postMessage(message, targetOrigin, transfer)
33+
```
34+
35+
上面写法中的`transfer`就是可传送物体。该物体一旦发送以后,所有权就转移到了目标窗口,当前窗口将无法再使用该物体。这样的设计是为了发送大量数据时,可以提高效率。
36+
37+
`targetOrigin``transfer`这两个参数,也可以写在一个对象里面,作为第二个参数。
38+
39+
```javascript
40+
window.postMessage(message, { targetOrigin, transfer })
41+
```
42+
43+
下面是一个跟弹出窗口发消息的例子。
44+
45+
```javascript
46+
const popup = window.open('http://example.com');
47+
popup.postMessage("hello there!", "http://example.com");
48+
```
49+
50+
`window.postMessage()`方法没有返回值。
51+
52+
## message 事件
53+
54+
当前窗口收到其他窗口发送的消息时,会发生 message 事件。通过监听该事件,可以接收对方发送的消息。
55+
56+
```javascript
57+
window.addEventListener(
58+
"message",
59+
(event) => {
60+
if (event.origin !== "http://example.com") return;
61+
// ...
62+
},
63+
false,
64+
);
65+
```
66+
67+
事件的监听函数,可以接收到一个 event 参数对象。该对象有如下属性。
68+
69+
- data:其他窗口发送的消息。
70+
- origin:发送该消息的窗口的源(协议+域名+端口)。
71+
- source:发送该消息的窗口对象的引用,使用该属性可以建立双向通信,下面是一个示例。
72+
73+
```javascript
74+
window.addEventListener("message", (event) => {
75+
if (event.origin !== "http://example.com:8080") return;
76+
event.source.postMessage(
77+
"hi there!",
78+
event.origin,
79+
);
80+
});
81+
```
82+
83+
## 实例
84+
85+
父页面是`origin1.com`,它打开了子页面`origin2.com`,并向其发送消息。
86+
87+
```javascript
88+
function sendMessage() {
89+
const otherWindow = window.open('https://origin2.com/origin2.html');
90+
const message = 'Hello from Origin 1!';
91+
const targetOrigin = 'https://origin2.com';
92+
otherWindow.postMessage(message, targetOrigin);
93+
}
94+
```
95+
96+
子页面`origin2.com`监听父页面发来的消息。
97+
98+
```javascript
99+
window.addEventListener('message', receiveMessage, false);
100+
101+
function receiveMessage(event) {
102+
if (event.origin === 'https://origin1.com') {
103+
console.log('Received message: ' + event.data);
104+
}
105+
}
106+
```
107+
108+
下面是 iframe 嵌入窗口向父窗口`origin1.com`发送消息的例子。
109+
110+
```javascript
111+
function sendMessage() {
112+
const message = 'Hello from Child Window!';
113+
window.parent.postMessage(message, 'https://origin1.com');
114+
}
115+
```
116+

0 commit comments

Comments
 (0)