跨页面通信

背景

在浏览器中每个页面都运行在单独的进程中,如何实现页面间的通信?

实现方案

BroadCastChannel

BroadcastChannel 接口代理了一个命名频道,可以让指定 origin 下的任意 browsing context 来订阅它。它允许同源的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间相互通信。通过触发一个 message 事件,消息可以广播到所有监听了该频道的 BroadcastChannel 对象。

  1. 构建一个实例
1
const bc = new BroadcastChannel('channel')
  1. 调用 postMessage 发送消息
1
bc.postMessage(data)
  1. 分别监听 onmessageonmessageerror 事件来接收数据和错误消息
1
2
3
4
5
6
bc.onmessage = function (e) {
// e.data是发送过来的数据,可以根据数据做一些事情
}
bc.onmessageerror = function (e) {
// 错误消息
}
  1. 调用 close 关闭通道,并销毁 BroadcastChannel 对象
1
bc.close()

localStorage 实现

当前页面使用的 storage 被其他页面修改时会触发 StorageEvent 事件

  1. 在源页面设置值触发事件
1
localStorage.setItem('newValue', 'new')
  1. 在接收页面监听 storage 事件以实现通信
1
2
3
4
window.addEventListener('storage', function (e) {
// e.newValue表示新设置的值
// e.key表示新设置的值的键
})

其它方案

  1. Service Worker: 一个可以长期运行在后台的 Worker,能够实现与页面的双向通信。
  2. Shared Worker: Worker 家族的另一个成员。普通的 Worker 之间是独立运行、数据互不相通;而多个 Tab 注册的 Shared Worker 则可以实现数据共享。
  3. IndexedDB: 数据存储技术
  4. window.open + window.opener: 当我们使用 window.open 打开页面时,方法会返回一个被打开页面 window 的引用。而在未显示指定 no opener 时,被打开的页面可以通过 window.opener 获取到打开它的页面的引用 —— 通过这种方式我们就将这些页面建立起了联系(一种树形结构)。
  5. visibilitychange: 当其选项卡的内容变得可见或被隐藏时,会在文档上触发 visibilitychange (能见度更改)事件。

参考