跨文檔消息傳送,簡稱爲XDM,指的是來自不一樣的域的頁面間的傳遞消息。 若是兩個網頁不一樣源,就沒法拿到對方的DOM。典型的例子是iframe窗口和window.open方法打開的窗口,它們與父窗口沒法通訊。html
好比,父窗口運行下面的命令,若是iframe窗口不是同源將會報錯。跨域
document.getElementById("iframe").contentWindow.document瀏覽器
上面命令中,父窗口想獲取子窗口的DOM,由於跨源致使報錯。安全
反之亦然,子窗口獲取主窗口的DOM也會報錯。dom
window.parent.document.body異步
若是兩個窗口一級域名相同,只是二級域名不一樣,那麼設置document.domain屬性,就可規避同源政策,拿到DOM。而 對於徹底不相同的網站,目前有三種方法,能夠解決跨域窗口的通訊問題。ide
(1) 片斷識別符(fragment identifier)post
片斷識別符指的是,URL的#號後面的部分,即hash部分,好比http://qq.com/x.html#fragment的#fragment。若是隻是改變片斷標識符,頁面將不會從新刷新,父窗口能夠把信息,寫入子窗口的片斷標識符。性能
var src = originURL+'#'+data;網站
document.getElementById('iframe').src = src;
子窗口經過監聽hashchange事件獲得通知
window.onhashchange = checkMessage;
function checkMessage(){
var message = window.location.hash;
//...
}
一樣的,子窗口也能夠改變父窗口的片斷標識符。
parent.location.href = target+"#"+hash;
(2) window.name
瀏覽器窗口有window.name屬性。這個屬性的最大特色是,不管是否同源,只要在同一個窗口裏,前一個網頁設置這個屬性,後一個網頁就能夠讀取它。
父窗口先打開一個子窗口,載入一個不一樣源的網頁,該網頁將信息寫入window.name屬性。
window.name = data;
接着,子窗口跳回一個與主窗口同域的網址。
location = 'http://parent.url.com/xxx.html';
而後,主窗口就能夠讀取子窗口的window.name了。
var data = document.getElementById('iframe').contentWindow.name;
這種方法的優勢是,window.name容量很大,能夠放置很是長的字符串;缺點是必須監聽子窗口window.name屬性的變化,會影響網頁性能。
(3) 跨文檔通訊API(Cross-document messaging)
上面兩種方法都屬於破解,HTML5爲解決這個問題,引入一個全新的API:跨文檔通訊API(Cross-document messaging)
這個API爲window對象新增了一個window.postMessage方法,容許跨窗口通訊,不論這兩個窗口是否同源。postMessage()方法接收兩個參數:一條消息和一個表示消息接收方來自哪一個域的字符串,第二個參數對保障安全通訊很是重要,能夠防止瀏覽器把消息發送到不安全的地方。 舉例來講,父窗口http://aaa.com向子窗口http://bbb.com發送消息,調用postMessage方法便可。
var popup =window.open('http://aaa.com','title');
popup.postMessage('Hello World!','http://aaa.com');
postMessage方法的第一個參數是具體的信息內容,第二個參數是接受消息的窗口的源(origin),即「協議+域名+端口」。也能夠設爲「*」,表示不限制域名,向全部窗口發送。
子窗口向父窗口髮型消息的寫法相似。
window.opener.postMessage('Nice to see you','http://bbb.com');
接收到XDM的消息時,會觸發window對象的message事件,這個事件以異步形式觸發,因此可能會發生一些延遲。 觸發message事件後,傳遞給onmessage處理程序的事件對象event包含如下三方面的重要信息:
(1).event.source:發送消息的窗口
(2).event.origin:消息發向的網站
(3).event.data:消息內容
父窗口和子窗口能夠經過message事件,監聽對方的消息。
window.addEventListener('message',function(e){
console.log(e.data);
},false);
下面的例子是,子窗口經過event.source屬性應用父窗口,而後發送消息。
window.addEventListener('message',receiveMessage);
function receiveMessage(event){
event.soure.postMessage('Nice to see you!','*');
}
event.origin屬性能夠過濾不是發給本窗口的消息。
window.addEventListener('message',receiveMessage);
function receiveMessage(event){
if(event.orgin !== 'http://bbb.com') return;
if(event.data === 'Hello World'){
event.soure.postMessage('Hello',event.source);
}else{
console.log(event.data);
}
}
片斷識別符指的是,URL的#號後面的部分,好比http://qq.com/x.html#fragment的#fragment。若是隻是改變片斷標識符,頁面將不會從新刷新、
父窗口能夠把信息,寫入子窗口的片斷標識符。
var src = originURL+'#'+data;
document.getElementById('iframe').src = src;
子窗口經過監聽hashchange事件獲得通知
window.onhashchange = checkMessage;
function checkMessage(){
var message = window.location.hash;
//...
}
一樣的,子窗口也能夠改變父窗口的片斷標識符。
parent.location.href = target+"#"+hash;