平時作web開發的時候關於消息傳遞,除了客戶端與服務器傳值還有幾個常常會遇到的問題javascript
1.頁面和其打開的新窗口的數據傳遞css
2.多窗口之間消息傳遞html
3.頁面與嵌套的iframe消息傳遞html5
4.上面三個問題的跨域數據傳遞java
這些問題都有一些解決辦法,但html5引入的message的API能夠更方便、有效、安全的解決這些難題。postMessage()方法容許來自不一樣源的腳本採用異步方式進行有限的通訊,能夠實現跨文本檔、多窗口、跨域消息傳遞。web
postMessage(data,origin)方法接受兩個參數json
1.data:要傳遞的數據,html5規範中提到該參數能夠是JavaScript的任意基本類型或可複製的對象,然而並非全部瀏覽器都作到了這點兒,部分瀏覽器只能處理字符串參數,因此咱們在傳遞參數的時候須要使用JSON.stringify()方法對對象參數序列化,在低版本IE中引用json2.js能夠實現相似效果。跨域
2.origin:字符串參數,指明目標窗口的源,協議+主機+端口號[+URL],URL會被忽略,因此能夠不寫,這個參數是爲了安全考慮,postMessage()方法只會將message傳遞給指定窗口,固然若是願意也能夠建參數設置爲"*",這樣能夠傳遞給任意窗口,若是要指定和當前窗口同源的話設置爲"/"。瀏覽器
http://test.com/index.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傳遞消息
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(e){ if(e.source!=window.parent) return; var color=container.style.backgroundColor; window.parent.postMessage(color,'*'); },false);
這樣咱們就能夠接收任何窗口傳遞來的消息了,爲了安全起見,咱們利用這時候的MessageEvent對象判斷了一下消息源,MessageEvent是一個這樣的東東
有幾個重要屬性
這樣就能夠接收跨域的消息了,咱們還能夠發送消息回去,方法相似
在這個例子中,左邊的div會根據右邊iframe內div顏色變化而變化
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Post Message</title> 5 </head> 6 <body> 7 <div style="width:200px; float:left; margin-right:200px;border:solid 1px #333;"> 8 <div id="color">Frame Color</div> 9 </div> 10 <div> 11 <iframe id="child" src="http://lsLib.com/lsLib.html"></iframe> 12 </div> 13 14 <script type="text/javascript"> 15 16 window.onload=function(){ 17 window.frames[0].postMessage('getcolor','http://lslib.com'); 18 } 19 20 window.addEventListener('message',function(e){ 21 var color=e.data; 22 document.getElementById('color').style.backgroundColor=color; 23 },false); 24 </script> 25 </body> 26 </html>
1 <!doctype html> 2 <html> 3 <head> 4 <style type="text/css"> 5 html,body{ 6 height:100%; 7 margin:0px; 8 } 9 </style> 10 </head> 11 <body style="height:100%;"> 12 <div id="container" onclick="changeColor();" style="widht:100%; height:100%; background-color:rgb(204, 102, 0);"> 13 click to change color 14 </div> 15 <script type="text/javascript"> 16 var container=document.getElementById('container'); 17 18 window.addEventListener('message',function(e){ 19 if(e.source!=window.parent) return; 20 var color=container.style.backgroundColor; 21 window.parent.postMessage(color,'*'); 22 },false); 23 24 function changeColor () { 25 var color=container.style.backgroundColor; 26 if(color=='rgb(204, 102, 0)'){ 27 color='rgb(204, 204, 0)'; 28 }else{ 29 color='rgb(204,102,0)'; 30 } 31 container.style.backgroundColor=color; 32 window.parent.postMessage(color,'*'); 33 } 34 </script> 35 </body> 36 </html>
在例子中頁面加載的時候主頁面向iframe發送’getColor‘ 請求(參數沒實際用處)
window.onload=function(){ window.frames[0].postMessage('getcolor','http://lslib.com'); }
iframe接收消息,並把當前顏色發送給主頁面呢
window.addEventListener('message',function(e){ if(e.source!=window.parent) return; var color=container.style.backgroundColor; window.parent.postMessage(color,'*'); },false);
主頁面接收消息,更改本身div顏色
window.addEventListener('message',function(e){ var color=e.data; document.getElementById('color').style.backgroundColor=color; },false);
當點擊iframe事觸發其變色方法,把最新顏色發送給主頁面
function changeColor () { var color=container.style.backgroundColor; if(color=='rgb(204, 102, 0)'){ color='rgb(204, 204, 0)'; }else{ color='rgb(204,102,0)'; } container.style.backgroundColor=color; window.parent.postMessage(color,'*'); }
主頁面仍是利用剛纔監聽message事件的程序處理自身變色
window.addEventListener('message',function(e){ var color=e.data; document.getElementById('color').style.backgroundColor=color; },false);
很簡單的用法卻解決了大問題,聽說Facebook已經在使用了,並且這也是html5另外一個API——web workers傳遞消息的方法,那麼它的瀏覽器兼容性怎麼樣呢?所謂瀏覽器兼容性幾乎變成了IE幾開始支持的問題了。。。不過好消息是跟localStorage同樣,IE8+都支持了,只不過有些瀏覽器的低版本(好比FireFox4.0)並不支持window.onmessage=function(){}這種寫法,因此我麼最好使用事件綁定的寫法,爲了兼容IE,也要判斷是否支持addEventListener。