最近做项目的时候使用arcgis api的popup与echarts图表相结合展示,然而由于popup属于动态生成,生成时间点无法获取,导致echarts无法绑定至popup中(不论是promise.then()方法,还是创建div时使用createElement()方法,都无法生效。setTimeout()方法应该可以,暂还未尝试)。因此,在popup中使用了<iframe>框架来获取其他页面的echarts.因此就需要进行不同页面间的数据传递。

一、postMessage()传递信息

postMessage()属于js的window方法,安全地启用Window对象之间的跨源通信;

postMessage()方法语法

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

其中:

targetWindow 对将接收消息的窗口的引用。获得此类引用的方法包括:

  • Window.open (生成一个新窗口然后引用它),
  • Window.opener (引用产生这个的窗口),
  • HTMLIFrameElement.contentWindow<iframe>从其父窗口引用嵌入式),
  • Window.parent(从嵌入式内部引用父窗口<iframe>
  • Window.frames +索引值(命名或数字)。

message 要发送到其他窗口的数据。使用结构化克隆算法序列化数据。这意味着您可以将各种各样的数据对象安全地传递到目标窗口,而无需自己序列化。

targetOrigin 指定要调度的事件的targetWindow的原点,可以是文字字符串"*"(表示没有首选项),也可以是URI。如果在计划调度事件时,targetWindow文档的方案,主机名或端口与targetOrigin提供的内容不匹配,则不会调度该事件;只有当所有的三个条件都匹配时,将调度该事件。该机制可以控制发送消息的位置;例如,如果postMessage()用于传输密码,则该参数必须是URI,其来源与包含密码的消息的预期接收者相同,以防止恶意第三方拦截密码。始终提供具体的targetOrigin,而不是*,如果您知道其他窗口的文档应该位于何处。未能提供特定目标会泄露您发送给任何感兴趣的恶意站点的数据。

transfer(可选的)是与消息一起传输的Transferable对象序列。这些对象的所有权将提供给目标端,并且它们在发送端不再可用。

注意:

原则上,postMessage()方法可以传递任何参数,但是不同浏览器上允许传递接收的参数不同,大部分浏览器仅支持传递字符串。经测试。谷歌浏览器允许传递接收string类型,boolean类型,Array类型,不允许传递接收Object类型。

二、addEventListener()监听信息传递后添加事件

addEventListener()是DOM方法,用于向指定元素添加事件句柄。我们通过addEventListener()方法给传递过来的Message添加事件。

addEventListener()方法语法

element.addEventListener(event, function, useCapture)

其中:

 

event 必须,字符串,指定事件名。

function 必须,指定要事件触发时执行的函数。 当事件对象会作为第一个参数传入函数。 事件对象的类型取决于特定的事件。例如, "click" 事件属于 MouseEvent(鼠标事件) 对象。

useCapture 指可选。布尔值,指定事件是否在捕获或冒泡阶段执行。 可能值:

    • true - 事件句柄在捕获阶段执行
    • false- false- 默认。事件句柄在冒泡阶段执行

三、<iframe>框架传递示例

主页面:(http://域名/main.html

<!DOCTYPE html> 
<html>
<head>
<meta charset="utf-8">
<title>主页面</title>
</head>
<body>
    <h1>主页面</h1>
    <iframe id="iframePopup" src="http://域名/test/"></iframe>
    <div>
        <h2>主页面接收消息区域</h2>
        <span id="messageReturn"></span>
    </div>
</body> 
</html>
<script>
    window.onload = function(){
        //父页面发送消息
        var iframePopup=document.getElementById('iframePopup')
         .contentWindow;
        iframePopup.postMessage("主页面消息", 
                "http://域名/test/")

        //父页面接收iframe子页面返回信息
        window.addEventListener('message',function(event){
            console.log(event);
            document.getElementById('messageReturn').innerHTML = "收到" + event.origin + "消息:" + event.data; }, false);
    } 
</script>

<iframe>框架页面:(http://域名/test

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>iframe子页面</title>
</head>
<body>
    <h2>iframe子页面</h2>
    <div>
        <h3>接收消息区域</h3>
        <span id="message"></span>
    </div>
</body>
</html>
<script>
    //iframe子页面接收信息
    window.addEventListener('message',function(event){
        console.log(event);
        document.getElementById('message').innerHTML = "收到" 
            + event.origin + "消息:" + event.data;
    }, false);

    //iframe子页面接收信息后回复父页面信息
    window.addEventListener('message',function(event){
        console.log(event);
        document.getElementById('message').innerHTML = "收到" 
            + event.origin + "消息:" + event.data;
        top.postMessage("子页面消息收到", 'http://域名/main.html')
    }, false);
</script>