實現兩個視窗通訊方法之-postMessage
阿新 • • 發佈:2018-11-13
兩個視窗的通訊問題應該是一個比較常見的問題了,通訊可以通過很多種方式,如下:
localStorage
postMessage
websocket
平時做web開發的時候關於訊息傳遞,除了客戶端與伺服器傳值還有幾個經常會遇到的問題
1.頁面和其開啟的新視窗的資料傳遞
2.多視窗之間訊息傳遞
3.頁面與巢狀的iframe訊息傳遞
4.上面三個問題的跨域資料傳遞
postMessage()
這些問題都有一些解決辦法,但html5引入的message的API可以更方便、有效、安全的解決這些難題。postMessage()方法允許來自不同源的指令碼採用非同步方式進行有限的通訊,可以實現跨文字檔、多視窗、跨域訊息傳遞。
postMessage(data,origin)方法接受兩個引數
1.data:要傳遞的資料,html5規範中提到該引數可以是JavaScript的任意基本型別或可複製的物件,然而並不是所有瀏覽器都做到了這點兒,部分瀏覽器只能處理字串引數,所以我們在傳遞引數的時候需要使用JSON.stringify()方法對物件引數序列化,在低版本IE中引用json2.js可以實現類似效果。
2.origin:字串引數,指明目標視窗的源,協議+主機+埠號[+URL],URL會被忽略,所以可以不寫,這個引數是為了安全考慮,postMessage()方法只會將message傳遞給指定視窗,當然如果願意也可以建引數設定為"*",這樣可以傳遞給任意視窗,如果要指定和當前視窗同源的話設定為"/"。
傳送訊息:
//父頁面: http://test.com/index.html //html <div style="width:200px; float:left; margin-right:200px;border:solid 1px #333;"> <div id="color">Frame Color</div> </div> <div> <iframe id="child" src="http://lsLib.com/lsLib.html"></iframe> </div> 我們可以在http://test.com/index.html通過postMessage()方法向跨域的iframe頁面http://lsLib.com/lsLib.html傳遞訊息 //js window.onload=function(){ window.frames[0].postMessage('getcolor','http://lslib.com'); }
接收訊息:
test.com上面的頁面向lslib.com傳送了訊息,那麼在lslib.com頁面上如何接收訊息呢,監聽window的message事件就可以
//子頁面: http://lslib.com/lslib.html
window.addEventListener('message',function(event){
if(event.source!=window.parent) return;
var color=container.style.backgroundColor;
window.parent.postMessage(color,'*');
},false);
這裡的event是MessageEvent的例項,裡面包含了data、origin、source屬性。data是傳送方傳送的message,origin是傳送方所屬的域,source是傳送方的window物件的引用。
若想要 將iframe的資訊,傳遞的父級頁面,則需要這樣寫:父級頁面也接收一下子頁面傳送的資訊即可
//父頁面:
window.addEventListener('message',function(event){
console.log(event)
if(event.source!=window.parent) return;
// var color=container.style.backgroundColor;
// window.parent.postMessage(color,'*');
},false);
//iframe的 子頁面
parent.postMessage('我是誰', 'http://test.com/index.html'); // 若父頁面的域名和指定的不一致,則postMessage失敗
案例2:
//a.com/index.html
<iframe src="b.com/index.html" id="ifr">
</iframe>
<script>
window.onload = function(){
var iframe = document.getElementById('ifr');
var targetOrigin = 'http://b.com'; // 若寫成'http://b.com/c/proxy.html'效果一樣
// 若寫成'http://c.com'就不會執行postMessage了
iframe.contentWindow.postMessage('data to send',targetOrigin);
}
</script>
// b.com/index.html
<script type="text/javascript">
window.addEventListener('message',function(event){
// 通過origin屬性判斷訊息來源地址
if(event.origin == 'http://a.com'){
console.log(event.data);
console.log(event.source);
}
},false);
</script>