在不同源页面通信的方法

491 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

在不同源页面中通信

跨文档消息(XDM)是一个在不同执行上下文中传递消息的能力。

核心

核心是利用 postMessage() 方法,可以把一个数据传递到另一个地方,另一个地方监听,然后拿到数据。 但是前提是双方都要同意并且调用相应的js。

以下是这个方法的两个部分

postMessage

postMessage() 方法接受三个参数

参数:

  • data

    要发送的数据。可以是任何对象,数据会被通过使用序列化进行克隆。IE 浏览器只支持字符串,因此我们需要对复杂的对象调用 JSON.stringify 方法进行处理,我们最好是转化 string 字符串,避免有些浏览器不支持。

  • targetOrigin

    指定目标窗口的源,以便只有来自给定的源的窗口才能获得该消息。

<iframe src="http://example.com" name="example">
<script>
    let win = window.frames.example;
    win.postMessage("message", "http://example.com");
</script>

现在只有example.com下的消息才会被win接收,这样的安全策略很重要

也可以把targetOrigin设置为 * 但是不建议这样。。。

onMessagge

为了接收数据,目标窗口会有一个message的事件,等发送了消息,并且检查targetOrigin成功。

event 事件对象具有特殊属性:

  • data

    从 postMessage 传递来的数据。

  • origin

    发送方的源,例如 http://example.com

  • source

    对发送方窗口的引用。如果我们想,我们可以立即 source.postMessage(...) 回去。

要为 message 事件分配处理程序,我们应该使用 addEventListener,简短的语法 window.onmessage 不起作用。

使用如下

window.addEventListener("message", function(event) {
  if (event.origin != 'http://example.com') {
    // 来自未知的源的内容,我们忽略它
    return;
  }

  alert( "received: " + event.data );

  // 可以使用 event.source.postMessage(...) 向回发送消息
});

总结

要调用另一个窗口的方法或者访问另一个窗口的内容,我们应该首先拥有对其的引用。

就是要过去到窗口,比如

  • window.frames —— 一个嵌套的 window 对象的集合,
  • window.parentwindow.top 是对父窗口和顶级窗口的引用,
  • iframe.contentWindow 是 <iframe> 标签内的 window 对象。

如果是同源的话,可以进行操作,不同源的话只能如下

  • 更改另一个窗口的 location(只能写入)。
  • 向其发送一条消息。

postMessage 接口可以让两个不同源的窗口通讯:

  1. 发送方调用 targetWin.postMessage(data, targetOrigin)

  2. 如果 targetOrigin 不是 '*',那么浏览器会检查窗口 targetWin 是否具有源 targetOrigin

  3. 如果它具有,targetWin 会触发具有特殊的属性的 message 事件:

    • origin —— 发送方窗口的源(比如 http://my.site.com)。
    • source —— 对发送方窗口的引用。
    • data —— 数据,可以是任何对象。但是 IE 浏览器只支持字符串,因此我们需要对复杂的对象调用 JSON.stringify 方法进行处理,以支持该浏览器。

    我们应该使用 addEventListener 来在目标窗口中设置 message 事件的处理程序。