补充一下,这里的通信指遵照同源策略状况下。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
------
其余