主頁面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
