postMessage解决跨域、消息传递

使用背景:其他平台嵌入到自己项目平台上,使用iframe做嵌套,但是涉及到进来免登录以及跨域问题,使用postMessage发送信息。

想要使用 postMessage 实现跨域通信和页面间数据通信,只要记住 window 提供的 postMessage 方法和 message 事件。

1、发送消息:

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

otherWindow
其他窗口的一个引用。比如 iframe 的 contentWindow 属性、执行 window.open 返回的窗口对象、或者是命名过或数值索引的 window.frames。

message
要发送的消息。它将会被结构化克隆算法序列化,所以无需自己序列化,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化。

targetOrigin
“目标域“。URI(包括:协议、主机地址、端口号)。若指定为”*“,则表示可以传递给任意窗口,指定为”/“,则表示和当前窗口的同源窗口。当为URI时,如果目标窗口的协议、主机地址或端口号这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会发送。

2、接收消息
如果指定的源匹配的话,那么当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件。
获取postMessage传来的消息:为页面添加onmessage事件。

window.addEventListener('message',function(e) {
   var origin = event.origin;
   // 通常,onmessage()事件处理程序应当首先检测其中的origin属性,忽略来自未知源的消息
   if (origin !== "http://example.org:8080") return;
   // ...
}, false)

event 的属性有:

data: 从其他 window 传递过来的数据副本。
origin: 调用 postMessage 时,消息发送窗口的 origin。例如:“http://example.com:8080”。
source: 对发送消息的窗口对象的引用。可以使用此来在具有不同 origin 的两个窗口之间建立双向数据通信。

小demo参考下:
http://www.domain1.com/a.html

<iframe id="iframe" src="http://www.domain2.com/b.html"></iframe>
 
<script>
var iframe = document.getElementById('iframe');
 
iframe.onload = function() {
   // 向domain2发送跨域数据
   iframe.contentWindow.postMessage('来自domain1的消息', 'http://www.domain2.com');
   //或  window.frames[0].postMessage('来自domain1的消息', 'http://www.domain2.com');
};
 
// 接受domain2返回数据
window.addEventListener('message',(e) => {
    console.log(e.data);
}, false);
</script>

http://www.domain2.com/b.html

<script>
// 接收domain1的数据
window.addEventListener('message',(e) => {
    console.log(e.data);
 
    if(e.origin !== 'http://www.domain1.com') return;
 
    // 发送消息给domain1
    window.parent.postMessage('来自domain2的消息', e.origin);
    // 或 window.top.postMessage('来自domain2的消息', e.origin);
    // 或 e.source.postMessage('来自domain2的消息', e.origin);
}, false);
</script>

项目真实使用:
index.vue

<template>
  <div
  >
    <iframe
      id="yhPage"
      src="http://192.168.5.58:8002/#/user/login"
      sandbox="allow-same-origin allow-top-navigation allow-forms allow-scripts"
      allow="payment"
      frameborder="0"
      orgin="*"
      style="width: 100vw; height: 100vh"
    ></iframe>
  </div>
</template>
  <script>
export default {
  data() {
    return {
      isShow: false,
    };
  },
  created() {
    const YHData = JSON.parse(localStorage.getItem("YHData"));
    // send data to yh
    setTimeout(() => {
      document.getElementById("yhPage").contentWindow.postMessage(
        {
          data: YHData,
        },
        // 与iframe嵌套的地址一致
        "http://192.168.5.58:8002"
      );
    }, 500);
    //
    setTimeout(() => {
      this.isShow = true;
    }, 600);
  },
};
</script>

嵌入项目组要接收数据:

login.vue页面

created(){
	window.addEventListener('meaasge', e=>{
	console.log('fff')
	if(e.origin.indexOf(9095) > -1){
		// 处理接收到的数据
		console.log(e.data)
		}

})
	}

你可能感兴趣的:(vue.js)