第19章 postMessage

261 阅读2分钟

一、前言

postMessage 是HTML5引入的API,postMessage() 方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档,多窗口,跨域消息传递。多用于窗口间数据通信,这也使它成为跨域通信的一种有效的解决方案。

1. 兼容性

查看兼容 >>

post_message.png

2. message 事件对象

message 事件包含5个只读属性:

  • data:包含任意字符串数据,由原始脚本发送
  • origin:一个字符串,包含原始文档的方案、域名以及端口(如:domain.example:80)
  • lastEventId:一个字符串,包含了当前的消息事件的唯一标识符。
  • source:原始文件的窗口的引用。更确切地说,它是一个WindowProxy对象
  • ports:一个数组,包含任何MessagePort对象发送消息。

在跨文档通信和通道通信中,lastEventId的值一般是个空字符串;lastEventId应用在服务器端发送事件上。发送信息中如果没有ports, 则 ports 属性值就是个长度为 0 的数组。

MessageEvent继承DOM事件接口,且属性共享。然而,通信事件并没有冒泡,不能取消,也没有默认行为。

二、API

1. 发送数据

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow:其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames
  • message:将要发送到其他 window的数据。
  • targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,指定后只有对应origin下的窗口才可以接收到消息,设置为通配符(*)表示可以发送到任何窗口,但通常处于安全性考虑不建议这么做.,如果想要发送到与当前窗口同源的窗口可设置为 /
  • transfer | 可选属性:是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

2. 接收数据

window.addEventListener("message", receiveMessage, false) ;
function receiveMessage(event) {
     var origin= event.origin;
     console.log(event);
}

三、示例

父窗口:

<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>INDEX PAGE</title>
</head>

<body>
  <div style="margin-bottom: 16px;">
    <input placeholder="请输入您要发送的信息" />
    <br />
    <br />
    <button type="button">发送</button>
  </div>
  <iframe src="http://127.0.0.1:5500/index.html"></iframe>
</body>

<script>
  // 1. 发送消息给子窗口
  const iframe = document.querySelector('iframe');
  const input = document.querySelector('input');
  const button = document.querySelector('button');

  button.addEventListener('click', () => {
    iframe.contentWindow.postMessage(input.value, '*')
  }, false);
  // 2. 监听子窗口返回的消息
  window.addEventListener('message', e => {
    console.log(e.data);
  }, false)

</script>

</html>

子窗口:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>OTHER PAGE</title>
</head>

<body>
  <div>Sub window recived message is:</div>
  <div class="ct"></div>
  <script>
    const ct = document.querySelector('.ct');
    window.addEventListener('message', e => {
      ct.textContent = e.data;
      parent.postMessage('信息已收到!', '*')
    }, false);
  </script>
</body>


</html>

四、参考