返回首页

浏览器多窗口通信技术

布莱克2026-06-02 20:33已编辑
Tip:文章封面与内容无关,作者旅游时拍摄,因为没什么值得把四季都错过!

浏览器多窗口通信技术

## 举个例子就是,假如一个浏览器打开了多个相同的窗口,其中某个窗口调用了编辑接口,数据更新了,其他的窗口数据怎么自动更新,不能手动刷新页面

  • 同域:协议、域名、端口完全一致(如 http://localhost:8080 的两个标签页),大部分原生 API 可直接通信;
  • 跨域:三者任一不同(如 http://a.comhttp://b.com),仅少数 API 支持(需显式授权)

同域多窗口通信

1.LocalStorage 监听(最常用)

原理:

  • 同域下,所有窗口共享 LocalStorage/SessionStorage 数据;
  • 当 A 窗口修改存储数据时,浏览器会在其他同域窗口触发 storage 事件(当前修改窗口不触发),监听该事件即可获取数据
// 窗口A(编辑数据或其他更新操作后)
localStorage.setItem('dataUpdated', JSON.stringify({
  type: 'message',
  content: 'Hello 窗口B'
}));

// 窗口B(监听变化)
window.addEventListener('storage', (e) => {
    if (e.key === 'dataUpdated') {
        const data = JSON.parse(e.newValue);
        console.log('收到消息:', data.content); // 输出:Hello 窗口B
        // 重新获取数据
        refresh();
    }
});
特性说明
优点兼容性最好(IE8+)、实现简单、数据持久化
缺点只能传字符串、同值不触发、有大小限制(5-10MB)
场景登录状态同步、主题切换、购物车数量


2. BroadcastChannel API(广播频道)

原理:

  • 多个同域窗口创建「同名广播频道」(如 new BroadcastChannel('my-channel'));
  • 任意窗口通过频道发送消息,所有订阅该频道的窗口都会收到(包括发送方自身);
  • 频道支持主动关闭,避免内存泄漏

// 窗口A
const channel = new BroadcastChannel('data-update');
channel.postMessage({ type: 'dataUpdated' });

//接收方 窗口B
const channel = new BroadcastChannel('data-update');
channel.onmessage = (e) => {
    if (e.data.type === 'dataUpdated') {
        refresh();
    }
};
特性说明
优点API 极简、性能好、自动管理生命周期
缺点不支持 IE、无状态存储
场景跨标签页消息广播、实时通知同步


3.SharedWorker

原理:

  • 浏览器为同源的多窗口创建唯一的 Worker 进程,通过 MessagePort 进行通信
// worker.js - 广播给所有窗口
const ports = [];

self.addEventListener('connect', (e) => {
  const port = e.ports[0];
  ports.push(port);
  
  port.onmessage = (msg) => {
    // 广播给所有窗口(包括自己)
    ports.forEach(p => p.postMessage(msg.data));
  };
  
  port.start();
});

// 页面
const worker = new SharedWorker('worker.js');
worker.port.start();
worker.port.onmessage = (e) => console.log('收到:', e.data);
worker.port.postMessage('hello');
特性说明
优点共享连接、内存、定时器,性能最好
缺点API 复杂、调试困难
场景WebSocket连接复用、全局状态管理、统一缓存


方案选择:

需要跨窗口通信?
 │
 ├─ 1. 是否需要共享持续的连接或状态?
 │    ├─ 是 → **SharedWorker** (最强大,适合复杂场景)
 │    └─ 否 → 继续判断
 │
 ├─ 2. 是否需要支持老旧的 IE 浏览器?
 │    ├─ 是 → **localStorage + storage 事件** (兼容性最佳)
 │    └─ 否 → 继续判断
 │
 └─ 3. 只是简单、快速的页面间消息广播?
      ├─ 是 → **BroadcastChannel** (API 最简洁)
      └─ 否 → 考虑 `window.postMessage` (用于与 iframe/弹窗等特定窗口通信)
场景描述推荐方案核心理由代码示例思路
1. 共享后台连接
(如 WebSocket、SSE)
SharedWorker避免每个标签页都建立连接,节省服务器资源。连接逻辑写在 Worker 中,各页面通过 Worker 收发消息。
2. 多标签页状态同步
(登录状态、主题、购物车数量)
localStorage + storage 事件兼容性最好,数据有持久性,刷新页面不丢失。一个页面 setItem,其他页面监听 storage 事件来更新 UI。
3. 实时、简单的消息广播
(通知所有页面刷新、播放提示音)
BroadcastChannelAPI 极其简洁,性能好,专为此类场景设计。new BroadcastChannel('xxx') 然后 postMessage 即可。


assistant