主页面main.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <form> <input type='text' id='sr'> <button type='button' id='submit'>提交</button> </form> <div id='message'></div> <iframe src='./msgIframe.html'></iframe> <script> //通道通信 var port; var ifr = document.querySelector('iframe'); var eleBox = document.querySelector("#message"); var submit = document.querySelector("#submit"); submit.onclick=function(){ var srinput = document.querySelector("#sr"); //window.frames[0].postMessage(srinput.value, '*'); port.postMessage(srinput.value);//iframe加载后向本页面父窗口发送消息,从e中获取通道端口信息,然后可以通过此port向iframe窗口中发送消息 } window.addEventListener("message", function(e){ eleBox.innerHTML = '接受到的信息是:' + e.data; if(e.ports){ port=e.ports[0]; } }, false); //跨文档通信 /*var eleBox = document.querySelector("#message"); var submit = document.querySelector("#submit"); submit.onclick=function(){ var srinput = document.querySelector("#sr"); postMessage(srinput.value, '*'); } window.addEventListener("message", function(e){ eleBox.innerHTML = '接受到的信息是:' + e.data; }, false);*/ </script> </body> </html>
加载iframe页面,sub.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <div id='message'></div> <script> var port; var eleBox = document.querySelector("#message"); var channel = new MessageChannel(); window.addEventListener('DOMContentLoaded', function(e) { //向父窗口发送消息, window.parent.postMessage('发送页加载完毕', '*',[channel.port2]); /* channel.port1.addEventListener('message', function(e){ eleBox.innerHTML='通道获取的消息为:'+e.data; }, false); */ channel.port1.onmessage(function(e){ eleBox.innerHTML='通道获取的消息为:'+e.data; }) channel.port1.start(); } ,false); </script> </body> </html>
window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain
设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
window.postMessage() 方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个 MessageEvent
消息。 该MessageEvent
消息有四个属性需要注意: message 属性表示该message 的类型; data 属性为 window.postMessage 的第一个参数;origin 属性表示调用window.postMessage() 方法时调用页面的当前状态; source 属性记录调用 window.postMessage() 方法的窗口信息。
postMessage语法
otherWindow.postMessage(message, targetOrigin, [transfer]);
targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;
transfer:
可选是一串和message 同时传递的 Transferable
对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
Channel Messaging API允许两个独立的脚本在不同的浏览环境(浏览上下文)中连接到同一个文档(例如两个iframes框架或主文档和一个iframe框架,或两个文档通过SharedWorker
一个共享工作线程或 两个线程)进行直接通信,通过两端各有一个端口port的双向通道channel(或管道)来传递消息。
通道消息概念和使用
使用MessageChannel()
构造器创建消息通道。一旦创建,管道的两个端口可以通过MessageChannel.port1
和MessageChannel.port2
属性来访问。创建该通道的应用app使用port1,而应用app端口的另一端使用port2,你发送一个消息到port2,使用window.postMessage和两个参数(要发送的消息,以及传输所有权对象,本例中指端口本身)将端口转移到另一个浏览上下文。
当这些可传输的对象被转移时,它们在之前的上下文中被“中止”—它们之前所属的上下文。例如,一个端口在发送时不能被原始上下文使用。注意,目前只能传输ArrayBuffer
和MessagePort
对象。
其他浏览上下文可以使用 MessagePort.onmessage
来监听消息,并使用事件的data属性来获取消息内容。然后您可以使用MessagePort.postMessage
将消息发送回原始文档。
当你想停止发送消息时,可以调用MessagePort.close
来关闭端口。
Channel messaging interfaces/消息通道接口
创建一个新的消息通道来发送消息。
控制消息通道上的端口,允许从一个端口发送消息,并侦听到达另一个端口的消息。
一组MessagePorts; 一个允许同时向多个端口广播消息的实验性解决方案。
参考:
https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API