window.postMessage

一、window.postMessage 基础语法

1.为什么使用

对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数Document.domain设置为相同的值) 时,这两个脚本才能相互通信。

window.postMessage()则实现了不同页面脚本的跨域通信

2.语法

2-1 发送

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow, 其他窗口的一个引用
  • message: 要发送到其他 window的数据
  • targetOrigin: 指定哪些窗口能接收到消息事件, 其值可以是字符串"*"(表示无限制)或者一个URI

2-2 监听接收

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event) {
    // 安全:始终使用origin和source属性验证发件人的身份
    // 这里不准确,chrome没有这个属性
    // var origin = event.origin || event.originalEvent.origin;
    var origin = event.origin
    if (origin !== "http://example.org:8080")
        return;
    // ...
}

message 的属性有:

  • data: 从其他 window 中传递过来的对象
  • origin: 调用 postMessage 时消息发送方窗口的 origin
  • source: 对发送消息的窗口对象的引用; 使用此属性可实现不同origin的两个窗口双向通信

二、多场景通信

  • 多标签页通信
  • iframe嵌套通信

1.多标签页通信

/*
 * A窗口的域名是<http://example.com:8080>,以下是A窗口的script标签下的代码:
 */

var popup = window.open(...popup details...);
popup.postMessage("hello there!", "http://example.org");

function receiveMessage(event) {
  // 我们能相信信息的发送者吗?  (也许这个发送者和我们最初打开的不是同一个页面).
  if (event.origin !== "http://example.org")
    return;

  // event.source 是我们通过window.open打开的弹出页面 popup
  // event.data 是 popup发送给当前页面的消息 "hi there yourself!  the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
/*
 * 弹出页 popup 域名是<http://example.org>,以下是script标签中的代码:
 */

//当A页面postMessage被调用后,这个function被addEventListener调用
function receiveMessage(event) {
  // 验证了所受到信息的origin
  if (event.origin !== "http://example.com:8080")
    return;

  // event.source 就当前弹出页的来源页面
  // event.data 是 "hello there!"

  // 把event.source作为回信的对象,并且把event.origin作为targetOrigin
  event.source.postMessage("hi there yourself!  the secret response " + "is: rheeeeet!", event.origin);
}

window.addEventListener("message", receiveMessage, false);

2.iframe嵌套通信

主应用

<iframe src='https://lianpf.github.io' ref='iframe' id='iframe></iframe>

mounted() {
    this.$refs.iframe.contentWindow.postMessage({type:'initData', data: this.date}, this.$refs.iframe.src)
    window.addEventListener(
      'message',
      e => {
        // ...
      },
      false
    )
}

iframe: 地址https://lianpf.github.io

window.parent.postMessage({
    type: 'release',
    data: {
        schema: this.$refs.editor.preview,
        staticCode: this.$refs.editor.tempCustomJSCode,
        staticCodeUMD: compileCode
    }
})

mounted/create () {
    window.addEventListener(
      'message',
      e => {
        if(typeof e.data === 'string'){
            console.log('传递无效信息')
        } else {
            if(e.data.type) {
                console.log('正常发送数据')
                const receiveData = e.data
                if (receiveData.type) {
                    // TODO: 数据分发更新store
                    handleReceiveData(receiveData, vue)
                }
            }
        }
      },
      false
    )
}

参考


最后, 希望大家早日实现:成为编程高手的伟大梦想!
欢迎交流~

微信公众号

本文版权归原作者曜灵所有!未经允许,严禁转载!对非法转载者, 原作者保留采用法律手段追究的权利!
若需转载,请联系微信公众号:连先生有猫病,可获取作者联系方式!