最近做项目的时候使用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>