概述
當頁面嵌入一個iframe,或者打開一個子窗口。這個時候如果父窗口需要與子窗口之間通訊,如果直接用DOM訪問對方窗口window,會受到跨於安全機制影響。
javascript提供一個方法,可以解決這個問題,window.postMessage()
;
示例
1.與iframe通訊
主頁面:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <iframe id="iframe_1" src="http://192.168.5.136:10013/tmp_75.html"></iframe> <!-- <iframe id="iframe_1" src="./temp_1263.html"></iframe> --> <script type="text/javascript"> var iframe_1 = document.getElementById("iframe_1"); iframe_1.addEventListener("load", function(e){ e.target.contentWindow.postMessage({"foo": 1}, "*"); }, false); window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { console.log(event); } </script> </body> </html>
子頁面:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { console.log(event); window.parent.postMessage({"bar": 1}, "*"); } </script> </body> </html>
雙方頁面監聽"message"事件,父頁面等待子頁面加載完畢后調用子窗口的window.postMessage發送信息,子窗口收到信息后觸發"message"回調函數,回調函數中往父窗口的window.postMessage發送信息,父窗口收到消息后觸發"message"回調函數。
2.與子窗口通訊
跟iframe不同之處在於,可能是出於某種安全機制的設計,通過window.open返回的window對象無法讓父窗口監聽該window對象的事件。
這就意味着父窗口無法通過事件去得知子窗口何時加載完畢,並且在何時適合調用window.postMessage發送信息。
有一種解決辦法是讓子窗口通過window.opener對象,調用父窗口的方法來到通知它子窗口已經就緒。
主頁面:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <a id="a_1">open</a> <script type="text/javascript"> var a_1 = document.getElementById("a_1"); var win_1; a_1.addEventListener("click", function(e){ win_1 = window.open('./tmp_77.html','_blank','width=200,height=100'); }, false); window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { console.log(event); } function subWinReady(){ win_1.postMessage({"foo": 1}, "*"); } </script> </body> </html>
子頁面:
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <script type="text/javascript"> window.opener.postMessage({"bar": 1}, "*"); window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { console.log(event); } //調用父頁面方法 window.opener.subWinReady(); </script> </body> </html>
注意:這種方式在跨域下是無效的,因為跨域下雙方頁面不能通過獲取對方window對象直接調用其方法。