平時作web開發的時候關於消息傳遞,除了客戶端與服務器傳值,還有幾個常常會遇到的問題:html
newWin = window.open(..)
);postMessage
是html5引入的API能夠更方便、有效、安全的解決這些問題。postMessage()方法容許來自不一樣源的腳本採用異步方式進行有限的通訊,能夠實現跨文本檔、多窗口、跨域消息傳遞。html5
data:要傳遞的數據,
html5規範中提到該參數能夠是JavaScript的任意基本類型或可複製的對象,然而並非全部瀏覽器都作到了這點兒,部分瀏覽器只能處理字符串參數,因此咱們在傳遞參數的時候須要使用JSON.stringify()方法對對象參數序列化,在低版本IE中引用json2.js能夠實現相似效果。web
origin:字符串參數,指明目標窗口的源,協議+主機+端口號[+URL]
,URL會被忽略,因此能夠不寫,這個參數是爲了安全考慮,someWindow.postMessage()
方法只會在someWindow所在的源(url的protocol, host, port)和指定源一致時纔會成功觸發message event,固然若是願意也能夠將參數設置爲"*
",someWindow能夠在任意源,若是要指定和當前窗口同源的話設置爲"/
"。json
父頁面a.html:跨域
//> localhost:9011/a.html <h1 class="header">page A</h1> <div class="mb20"> <textarea name="ta" id="data" cols="30" rows="5">hello world</textarea> <button style="font-size:20px;" onclick="send()">post message</button> </div> <!-- 不跨域的狀況 --> <iframe src="b.html" id="child" style="display: block; border: 1px dashed #ccc; height: 300px;"></iframe> <script> function send() { var data = document.querySelector('#data').value; // 注意: 只會觸發當前window對象的message事件 // 也能夠訪問子頁面的window對象,觸發子頁面的message事件 (window.frames[0].postMessage(...)) // window.postMessage(data, '/'); // data = {name: 'sandy', age: 20, fav: {sing: true, shop: false}}; // 也能夠傳普通對象 window.frames[0].postMessage(data, '/'); // 觸發同域子頁面的message事件 //window.frames[0].postMessage(data, 'http://localhost:9022/'); // 觸發跨域子頁面的messag事件 } // 當前頁面執行 window.postMessage(..) // 或 // 子頁面執行 parent.postMessage(...) 都會觸發下面的回調, messageEvent.source不一樣而已 window.addEventListener('message', function(messageEvent) { var data = messageEvent.data;// messageEvent: {source, currentTarget, data} console.info('message from child:', data); }, false); </script>
子頁面b.html瀏覽器
//> localhost:9011/b.html <h1 class="header">page B</h1> <input type="text" id="inp" value="some contents.."> <button onclick="send()">send</button> <script> window.addEventListener('message', function(ev) { // if (ev.source !== window.parent) {return;} var data = ev.data; console.info('message from parent:', data); }, false); function send() { var data = document.querySelector('#inp').value; // window.postMessage(data, '*'); // 觸發當前頁面的message事件 parent.postMessage(data, '*'); // 觸發父頁面的message事件 // parent.postMessage(data, 'http://localhost:9011/'); // 若父頁面的域名和指定的不一致,則postMessage失敗 } </script>
父頁面a.html:安全
//> localhost:9011/a.html <h1 class="header">page A</h1> <div class="mb20"> <textarea name="ta" id="data" cols="30" rows="5">hello world</textarea> <button style="font-size:20px;" onclick="send()">post message</button> </div> <!-- 跨域的狀況 --> <iframe src="http://localhost:9022/b.html" id="child" style="display: block; border: 1px dashed #ccc; height: 300px;"></iframe> <script> function send() { var data = document.querySelector('#data').value; window.frames[0].postMessage(data, 'http://localhost:9022/'); // 觸發跨域子頁面的messag事件 } window.addEventListener('message', function(messageEvent) { var data = messageEvent.data; console.info('message from child:', data); }, false); </script>
子頁面b.html服務器
//> localhost:9022/b.html <h1 class="header">page B</h1> <input type="text" id="inp" value="some contents.."> <button onclick="send()">send</button> <script> window.addEventListener('message', function(ev) { // if (ev.source !== window.parent) {return;} var data = ev.data; console.info('message from parent:', data); }, false); function send() { var data = document.querySelector('#inp').value; parent.postMessage(data, 'http://localhost:9011/'); // 若父頁面的域名和指定的不一致,則postMessage失敗 // parent.postMessage(data, '*'); // 觸發父頁面的message事件 } </script>