f.contentWindow.postMessage("SB","http://localhost");javascript
<button id="send">Send Message</button>
<iframe id="receiver" src="http://demos.matt-west.com/post-message/receiver.html" width="400" height="200">html
<p>Your browser does not support iframes.</p>
</iframe>
java
window.onload = function() {
// Get the window displayed in the iframe.
var receiver = document.getElementById('receiver').contentWindow;
// Get a reference to the 'Send Message' button.
var btn = document.getElementById('send');windows
// A function to handle sending messages.
function sendMessage(e) {
// Prevent any default browser behaviour.
e.preventDefault();瀏覽器
// Send a message with the text 'Hello Treehouse!' to the receiver window.
receiver.postMessage('Hello Treehouse!', 'http://demos.matt-west.com');
}安全
// Add an event listener that will execute the sendMessage() function
// when the send button is clicked.
btn.addEventListener('click', sendMessage);
}app
<div id="message"></div>dom
<script src="receiver.js"></script>函數
window.onload = function() {
// Get a reference to the <div> on the page that will display the
// message text.
var messageEle = document.getElementById('message');post
// A function to process messages received by the window.
function receiveMessage(e) {
// Check to make sure that this message came from the correct domain.
if (e.origin !== "http://s.codepen.io")
return;
// Update the div element to display the message.
messageEle.innerHTML = "Message Received: " + e.data;
}
// Setup an event listener that calls receiveMessage() when the window
// receives a new MessageEvent.
window.addEventListener('message', receiveMessage);
}
來自《JavaScript 標準參考教程(alpha)》,by 阮一峯
所謂「同域限制」指的是,出於安全考慮,瀏覽器只容許腳本與一樣協議、一樣端口、一樣域名的地址進行通訊。好比,www1.example.com頁面上面的腳本,只能與該域名(相同協議、相同端口)進行通訊,若是與www2.example.com通訊,瀏覽器就會報錯(不過能夠設置二者的document.domain爲相同的值)。這是爲了防止惡意腳本將用戶信息發往第三方網站。
window.postMessage方法就是用來在某種程度上,繞過同域限制,實現不一樣域名的窗口(包括iframe窗口)之間的通訊。它的格式以下。
targetWindow.postMessage(message, targetURL[, transferObject]);
上面代碼的targetWindow是指向目標窗口的變量,message是要發送的信息,targetURL是指定目標窗口的網址,不符合該網址就不發送信息,transferObject則是跟隨信息一塊兒發送的Transferable對象。
下面是一個postMessage方法的實例。假定當前網頁彈出一個新窗口。
var popup = window.open(...popup details...); popup.postMessage("Hello World!", "http://example.org");
上面代碼的postMessage方法的第一個參數是實際發送的信息,第二個參數是指定發送對象的域名必須是example.org。若是對方窗口不是這個域名,信息不會發送出去。
而後,在當前網頁上監聽message事件。
window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { if (event.origin !== "http://example.org") return; if (event.data == 'Hello World') { event.source.postMessage('Hello', event.origin); } else { console.log(event.data); } }
上面代碼指定message事件的回調函數爲receiveMessage,一旦收到其餘窗口發來的信息,receiveMessage函數就會被調用。receiveMessage函數接受一個event事件對象做爲參數,該對象的origin屬性表示信息的來源網址,若是該網址不符合要求,就馬上返回,再也不進行下一步處理。event.data屬性則包含了實際發送過來的信息,event.source屬性,指向當前網頁發送信息的窗口對象。
最後,在popup窗口中部署下面的代碼。
// popup窗口 function receiveMessage(event) { event.source.postMessage("Nice to see you!", "*"); } window.addEventListener("message", receiveMessage, false);
上面代碼有幾個地方須要注意。首先,receiveMessage函數裏面沒有過濾信息的來源,任意網址發來的信息都會被處理。其次,postMessage方法中指定的目標窗口的網址是一個星號,表示該信息能夠向任意網址發送。一般來講,這兩種作法是不推薦的,由於不夠安全,可能會被惡意利用。
全部瀏覽器都支持這個方法,可是IE 8和IE 9只容許postMessage方法與iFrame窗口通訊,不能與新窗口通訊。IE 10容許與新窗口通訊,可是隻能使用IE特有的MessageChannel對象。
iframe中的網頁,若是與主頁面來自同一個域,經過設置document.domain屬性,能夠使用postMessage方法實現雙向通訊。
下面是一個LocalStorage的例子。LocalStorage只能用同一個域名的網頁讀寫,可是若是iframe是主頁面的子域名,主頁面就能夠經過postMessage方法,讀寫iframe網頁設置的LocalStorage數據。
iframe頁面的代碼以下。
document.domain = "domain.com"; window.onmessage = function(e) { if (e.origin !== "http://domain.com") { return; } var payload = JSON.parse(e.data); localStorage.setItem(payload.key, JSON.stringify(payload.data)); };
主頁面的代碼以下。
window.onload = function() { var win = document.getElementsByTagName('iframe')[0].contentWindow; var obj = { name: "Jack" }; win.postMessage(JSON.stringify({key: 'storage', data: obj}), "*"); };
上面的代碼已經能夠實現,主頁面向iframe傳入數據。若是還想讀取或刪除數據,能夠進一步增強代碼。
增強版的iframe代碼以下。
document.domain = "domain.com"; window.onmessage = function(e) { if (e.origin !== "http://domain.com") { return; } var payload = JSON.parse(e.data); switch(payload.method) { case 'set': localStorage.setItem(payload.key, JSON.stringify(payload.data)); break; case 'get': var parent = window.parent; var data = localStorage.getItem(payload.key); parent.postMessage(data, "*"); break; case 'remove': localStorage.removeItem(payload.key); break; } };
增強版的主頁面代碼以下。
window.onload = function() { var win = document.getElementsByTagName('iframe')[0].contentWindow; var obj = { name: "Jack" }; // 存入對象 win.postMessage(JSON.stringify({key: 'storage', method: "set", data: obj}), "*"); // 讀取之前存取的對象 win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*"); window.onmessage = function(e) { if (e.origin != "http://sub.domain.com") { return; } // 下面會輸出"Jack" console.log(JSON.parse(e.data).name); }; };