兩個瀏覽器視窗間通訊總結
1、localStorage
一個視窗更新localStorage,另一個視窗監聽window物件的”storage”事件,來實現通訊。
注:兩個頁面要同源(URL的協議、域名和埠相同)
// 本視窗的設值程式碼
localStorage.setItem('aaa',(Math.random()*10).toString())
// 其他視窗監聽storage事件
window.addEventListener("storage",function(e){
console.log(e)
console.log(e.newValue)
})
2、WebSocket
所有的WebSocket都監聽同一個伺服器地址,利用send傳送訊息,利用onmessage獲取訊息的變化,不僅能視窗,還能跨瀏覽器,相容性最佳,只是需要消耗點伺服器資源。
var ws =newWebSocket("ws://localhost:3000/")
ws.onopen =function(event){
// 或者把此方法註冊到其他事件中,即可與其他伺服器通訊
ws.send({now :Date.now()});// 通過伺服器中轉訊息
};
ws.onmessage =function(event){
// 消費訊息
console.log(event.data);
}
3、postMessage
藉助iframe 或 window.open
回顧一下API
otherWindow.postMessage(message, targetOrigin,[transfer]);
otherWindow
其他視窗的一個引用,比如iframe的contentWindow屬性、執行window.open返回的視窗物件、或者是命名過或數值索引的window.frames。message
將要傳送到其他 window的資料。它將會被結構化克隆演算法序列化。這意味著你可以不受什麼限制的將資料物件安全的傳送給目標視窗而無需自己序列化。targetOrigin
通過視窗的origin屬性來指定哪些視窗能接收到訊息事件,其值可以是字串""(表示無限制)或者一個URI。在傳送訊息的時候,如果目標視窗的協議、主機地址或埠這三者的任意一項不匹配targetOrigin提供的值,那麼訊息就不會被髮送;只有三者完全匹配,訊息才會被髮送。這個機制用來控制訊息可以傳送到哪些視窗;例如,當用postMessage傳送密碼時,這個引數就顯得尤為重要,必須保證它的值與這條包含密碼的資訊的預期接受者的origin屬性完全一致,來防止密碼被惡意的第三方截獲。如果你明確的知道訊息應該傳送到哪個視窗,那麼請始終提供一個有確切值的targetOrigin,而不是transfer 可選
是一串和message 同時傳遞的 Transferable 物件. 這些物件的所有權將被轉移給訊息的接收方,而傳送一方將不再保有所有權。
/*
* A視窗的域名是<http://example.com:8080>,以下是A視窗的script標籤下的程式碼:
*/
var popup = window.open(...popup details...);
// 如果彈出框沒有被阻止且載入完成
// 這行語句沒有傳送資訊出去,即使假設當前頁面沒有改變location(因為targetOrigin設定不對)
popup.postMessage("The user is 'bob' and the password is 'secret'",
"https://secure.example.net");
// 假設當前頁面沒有改變location,這條語句會成功新增message到傳送佇列中去(targetOrigin設定對了)
popup.postMessage("hello there!","http://example.org");
function receiveMessage(event)
{
// 我們能相信資訊的傳送者嗎? (也許這個傳送者和我們最初開啟的不是同一個頁面).
if(event.origin !=="http://example.org")
return;
// event.source 是我們通過window.open開啟的彈出頁面 popup
// event.data 是 popup傳送給當前頁面的訊息 "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage,false);
/*
* 彈出頁 popup 域名是<http://example.org>,以下是script標籤中的程式碼:
*/
//當A頁面postMessage被呼叫後,這個function被addEventListenner呼叫
function receiveMessage(event)
{
// 我們能信任資訊來源嗎?
if(event.origin !=="http://example.com:8080")
return;
// event.source 就當前彈出頁的來源頁面
// event.data 是 "hello there!"
// 假設你已經驗證了所受到資訊的origin (任何時候你都應該這樣做), 一個很方便的方式就是把enent.source
// 作為回信的物件,並且把event.origin作為targetOrigin
event.source.postMessage("hi there yourself! the secret response "+
"is: rheeeeet!",
event.origin);
}
window.addEventListener("message", receiveMessage,false);
4、cookie + setInterval【差】
在頁面A設定一個使用 setInterval 定時器不斷重新整理,檢查 Cookies 的值是否發生變化,如果變化就進行重新整理的操作。
由於 Cookies 是在同域可讀的,所以在頁面 B 稽核的時候改變 Cookies 的值,頁面 A 自然是可以拿到的。
這樣做確實可以實現我想要的功能,但是這樣的方法相當浪費資源。雖然在這個效能過盛的時代,浪費不浪費也感覺不出來,但是這種實現方案,確實不夠優雅。
5、SharedWorker
HTML5 中的 Web Worker 可以分為兩種不同執行緒型別,一個是專用執行緒 Dedicated Worker,一個是共享執行緒 Shared Worker。
Dedicated Worker直接使用new Worker()即可建立,這種webworker是當前頁面專有的。。
SharedWorker可以被多個window、標籤頁、iframe共同使用,但必須保證這些標籤頁都是同源的(相同的協議,主機和埠號)
6、直接引用
其實就是直接獲取對方DOM,適用於兩個頁面在同一域;可以傳遞物件資料(物件資料使用 instanceof 做型別判斷時有坑);參考 window.open;
例:
// 父頁面獲取子iframe
document.getElementById('iframe的id').contentWindow.document
// 子iframe獲取父頁面
window.parent.document
7、window.name
瀏覽器視窗有window.name屬性。這個屬性的最大特點是,無論是否同源,只要在同一個窗口裡,前一個網頁設定了這個屬性,後一個網頁可以讀取它。
父視窗先開啟一個子視窗,載入一個不同源的網頁,該網頁將資訊寫入window.name屬性。
window.name = data;
接著,子視窗跳回一個與主視窗同域的網址。
window.location.href ='http://parent.url.com/xxx.html';
然後,主視窗就可以讀取子視窗的window.name了。
var data = document.getElementById('iframe的id').contentWindow.name;
這種方法的優點是,window.name容量很大,可以放置非常長的字串;缺點是必須監聽子視窗window.name屬性的變化,影響網頁效能。
END
作者:baozw
https://segmentfault.com/a/1190000016927268