1. 程式人生 > >實現兩個視窗通訊方法之-postMessage

實現兩個視窗通訊方法之-postMessage

兩個視窗的通訊問題應該是一個比較常見的問題了,通訊可以通過很多種方式,如下:

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>