当浏览器同时打开多个tab时,前端有哪些方式进行通讯和数据共享?

核心想法是找到一个通用的第三方。这个第三方可以同时联系到标签一、标签二。(同样的逻辑,可以参考 vuex 或 pinia)

  1. BroadcastChannel
  • 适用场景: 同源的多个 Tab 需要简单高效的消息广播
  • 实现原理: BroadcastChannel 提供了一个发布/订阅模型,允许同源页面间传递消息。

Tab1 发送消息:

js 复制代码
const channel = new BroadcastChannel('my_channel');
channel.postMessage('Hi from Tab 1');

Tab2 发送消息:

js 复制代码
const channel = new BroadcastChannel('my_channel');
channel.onmessage = (event)=>{
  console.log('Received message:', event.data);
}
  • 优点: 简单易用,支持多 Tab 广播。
  • 限制: 需要页面同源,浏览器支持范围有限(现代浏览器支持良好)。
  1. LocalStorage + StorageEvent
  • 适用场景: 同源页面间低频、简单的状态同步。
  • 实现原理: localStorage 数据更新时,其他 Tab 会触发 storage 事件,页面可监听到数据变化。

Tab1 写入消息:

js 复制代码
localStorage.setItem('key', 'hi from Tab 1');

Tab2 监听变化:

js 复制代码
window.addEventListener('storage', (event)=>{
  if(event.key === 'key'){
    console.log('Received message:', event.newValue);
  }
})
  1. Service Worker
  • 适用场景: 需要多个 Tab 与后台服务共享信息或实现双向通信
  • 实现原理: 通过 Service Worker 的消息通道,Tab 可以与 Service Worker 通信,Service Worker 也可以作为中间层实现多个 Tab 间的消息转发。

Tab 发送消息到 Service Worker:

js 复制代码
navigator.serviceWorker.controller.postMessage('hi from Tab');

Service Worker 监听消息并广播:

js 复制代码
self.addEventListener('message', (event)=>{
  self.clients.matchAll().then(clients =>{
    clients.forEach(client => client.postMessage(event.data));
  })
})

Tab 接收消息:

js 复制代码
navigator.serviceWorker.addEventListener('message', (event) => {
  console.log('Received message:', event.data);
});
  1. SharedWorker
  • 适用场景: 需要多个同源 Tab 长连接并共享状态。
  • 实现原理: SharedWorker 允许多个 Tab 共享一个 Worker 线程,并通过消息通道通信。

SharedWorker文件(worker.js):

js 复制代码
onconnect = function(event) {
  const port = event.ports[0];
  port.onmessage = (e) => {
    console.log('Received from Tab:', e.data);
    port.postMessage('Message received in Worker');
  };
};

Tab 使用 SharedWorker:

js 复制代码
const worker = new SharedWorker('worker.js');
worker.port.onmessage = (event) => {
  console.log('Received from Worker:', event.data);
};
worker.port.postMessage('hi from Tab');
  • 优点: 支持双向通信,性能较好。
  • 限制: 需要同源,较少应用于简单场景,现代浏览器支持较好。
  1. WebSocket
  • 适用场景: 跨域或需要实时通信的复杂场景(不仅限于浏览器 Tab 通信)。
  • 实现原理: 多个 Tab 通过 WebSocket 连接同一个服务端,服务端转发消息。
js 复制代码
const socket = new WebSocket('wss://example.com/socket');
socket.onmessage = (event) => {
  console.log('Received message:', event.data);
};
socket.send('hi from Tab');
  • 优点: 不受同源限制,支持实时通信。
  • 限制: 需要服务端支持,需额外开发和维护。
  1. PostMessage + window.opener
  • 适用场景: 当 Tab 通过 window.open 打开的,支持父窗口与子窗口之间的通信。
  • 实现原理: 通过 postMessage 方法向特定窗口发送消息。

父窗口发送消息给子窗口:

js 复制代码
const childWindow = window.open('child.html');
childWindow.postMessage('hi from Parent', '*');

子窗口接收消息:

js 复制代码
window.addEventListener('message', (event) => {
  console.log('Received message:', event.data);
});
  • 优点: 灵活支持跨域通信。
  • 限制: 仅限于父子窗口,不能广播到多个Tab。
相关推荐
烛阴6 分钟前
Mix
前端·webgl
代码续发18 分钟前
前端组件梳理
前端
试图让你心动1 小时前
原生input添加删除图标类似vue里面移入显示删除[jquery]
前端·vue.js·jquery
陈不知代码1 小时前
uniapp创建vue3+ts+pinia+sass项目
前端·uni-app·sass
小王码农记1 小时前
sass中@mixin与 @include
前端·sass
陈琦鹏2 小时前
轻松管理 WebSocket 连接!easy-websocket-client
前端·vue.js·websocket
hui函数2 小时前
掌握JavaScript函数封装与作用域
前端·javascript
行板Andante2 小时前
前端设计中如何在鼠标悬浮时同步修改块内样式
前端
Carlos_sam3 小时前
Opnelayers:ol-wind之Field 类属性和方法详解
前端·javascript
小毛驴8503 小时前
创建 Vue 项目的 4 种主流方式
前端·javascript·vue.js