html5入门postMessageAPI

358 阅读3分钟

1. postMessage是什么?

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

2. postMessage API介绍

发送数据:

otherWindow.postMessage(message, targetOrigin, [transfer]);

其中相关的对象和参数说明如下,

  • otherWindow:其他窗口的一个引用,比如 iframe 的 contentWindow 属性、执行window.open 返回的窗口对象、或者是命名过或数值索引的 window.frames。
  • targetOrigin:通过窗口的 origin 属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个 URI。
  • message:将要发送到其他 window 的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。

接受数据:

window.addEventListener("message", receiveMessage);
function receiveMessage(event)
{
  var origin = event.origin
  if (origin !== "http://example.org:8080")
    return;
  // ...
}

event对象的打印结果截图如下:

image.png

3. PostMessage的原理

postMessage 是 html5 新引进的一个可跨源通信 api,你可以通过这个 api,让主页面和任意 frame 类页面或 window.open 打开的页面进行双向通信。它的大概运作流程如下图:

image.png

4. 举例说明

子页面向父页面传递消息

父页面
<!-- index.html -->
<iframe src="http://127.0.0.1:5500/frame1.html" frameborder="1"></iframe>
<iframe src="http://127.0.0.1:5500/frame2.html" frameborder="1"></iframe>
<script>
window.addEventListener('message',function(e){
  console.log(e.data)
},false)
</script>
子页面
<!-- frame1.html -->
<h1>iframe1 page</h1>
<script>
  window.top.postMessage('message from iframe1');
</script>

父页面向子页面传递消息

父页面
<!-- index.html -->
    <iframe src="http://127.0.0.1:5500/frame1.html" frameborder="1"></iframe>
    <iframe src="http://127.0.0.1:5500/frame2.html" frameborder="1"></iframe>
    <script>
        window.onload = function () {
            var frame1 = window.frames[0];
            frame1.postMessage('message from parentwindow', 'http://127.0.0.1:5500/frame1.html');
        }
    </script>
子页面
<!-- frame1.html -->
    <h1>iframe1 page</h1>
    <script>
        window.addEventListener('message',function(e){
            console.log(e.data)
        },false)
    </script>

注: window.postMessage中的window指的是你想发送跨域消息的那个窗口(你需要通信的目标窗口),而不是自身窗口的window

  • window.postMessage中的window指的是你想发送跨域消息的那个窗口(你需要通信的目标窗口),而不是自身窗口的window
    • 父页面中:父页面向子页面发送跨域信息,window就是在父页面中嵌入的iframe指向的子页面的window,即:iFrame.contentWindow
    • 子页面中:子页面想父页面发送跨域信息,window就是父页面的window,在这里因为子页面是嵌入到父页面中的,对于子页面来讲,window就是top或者parent
  • 需要等到iframe中的子页面加载完成后才发送消息,否则子页面接收不到消息
  • 在监听message事件时需要判断一下消息来源origin

5. postMessage的真正意义

如果仅仅只是为了解决ajax跨域,其实方案很多,像cors、jsonp等就足够了, postMessage 的价值体现,应该是能让两个不同的网页之间建立联动。

抛开postMessage,直接和某个网站通讯是不可行的,浏览器的安全策略会限制你的所有操作。这种情况下,你能通讯的就只有那个网站的服务器接口,通过跨域支持,实现信息交互。这种方式很稳健,缺点也比较明显:

  • 需要和对方服务器通讯,跨域是需要额外设置才能支持的,这个需要和对方沟通协商。
  • 如果需要提取对方网页里的某个值,或者通知对方有交互变化,除了通过ajax轮询,由服务器代为传递信息,别无它法。

6. postMessage的兼容性?

支持IE8+,不支持IE6和IE7。

image.png