補充一下,這裏的通信指遵照同源策略狀況下。html
爲了吸引讀者的興趣,先把demo放到前面:
下面有幾個我本身寫的演示多頁面通信的demo, 爲了正常運行,請用最新的chrome瀏覽器打開。
demo的源碼地址https://github.com/xiangwenhu/page-communication/tree/master/docs前端
爲何會扯到這個話題,最初是源於聽 https://y.qq.com/ QQ音樂,git
這裏我又聯想到了商城的購物車的場景,體驗確實有提高。
剛開始,我懷疑的是Web Socket做妖,結果經過分析網絡請求和看源碼,並無。 最後發現是localStore的storage事件做妖,哈哈。github
迴歸正題,其實在通常正常的知識儲備的狀況下,咱們會想到哪些方案呢?web
你能夠在The WebSocket API (WebSockets)看到更多的關於Web Socket的信息。chrome
定時器:setTimeout/setInterval/requestAnimationFrame
客戶端存儲: cookie/localStorage/sessionStorage/indexDB/chrome的FileSystemsegmentfault
定時器沒啥好說的,關於客戶端存儲。瀏覽器
提到上面的window.open, open後你能得到被打開窗體的句柄,固然也能夠直接操做窗體了。服務器
到這裏,我以爲通常的前端人員能想到的比較正經的方案應該是上面三種啦。
固然,咱們接下來講說可能不是那麼常見的另外三種方式。websocket
localStorage.setItem('message',JSON.stringify({ message: '消息', from: 'Page 1', date: Date.now() }))
Page 2
window.addEventListener("storage", function(e) { console.log(e.key, e.newValue, e.oldValue) });
如上, Page 1設置消息, Page 2註冊storage事件,就能監聽到數據的變化啦。
上面的e就是StorageEvent,有下面特有的屬性(都是隻讀):
使用起來也很簡單, 建立BroadcastChannel, 而後監聽事件。 只須要注意一點,渠道名稱一致就能夠。
Page 1
var channel = new BroadcastChannel("channel-BroadcastChannel"); channel.postMessage('Hello, BroadcastChannel!')
Page 2
var channel = new BroadcastChannel("channel-BroadcastChannel"); channel.addEventListener("message", function(ev) { console.log(ev.data) });
這裏來個插曲,Safari有幾個版本支持這個特性,後來又不支持啦,仍是你Safari,真是6。
雖然,SharedWorker自己的資源是共享的,可是要想達到多頁面的互相通信,那仍是要作一些手腳的。
先看看MDN給出的例子的ShareWoker自己的代碼:
onconnect = function(e) { var port = e.ports[0]; port.onmessage = function(e) { var workerResult = 'Result: ' + (e.data[0] * e.data[1]); port.postMessage(workerResult); } }
上面的代碼其實很簡單,port是關鍵,這個port就是和各個頁面通信的主宰者,既然SharedWorker資源是共享的,那好辦,把port存起來就是啦。
看一下,以下改造的代碼:
SharedWorker就成爲一個純粹的訂閱發佈者啦,哈哈。
var portList = []; onconnect = function(e) { var port = e.ports[0]; ensurePorts(port); port.onmessage = function(e) { var data = e.data; disptach(port, data); }; port.start(); }; function ensurePorts(port) { if (portList.indexOf(port) < 0) { portList.push(port); } } function disptach(selfPort, data) { portList .filter(port => selfPort !== port) .forEach(port => port.postMessage(data)); }
Broadcast
MDN Web Docs - Broadcast Channel
BroadcastChannel | Can I Use
broadcast-channel
BroadcastChannel that works in New Browsers, Old Browsers, WebWorkers and NodeJ
--------
StorageEvent
SharedWorker
SharedWorker
simple-shared-worker
SharedWorker | Can I Use
共享線程 SharedWorker
feature-shared-web-workers
------
其餘