🌐前端跨标签通信 6 大杀器:从 1KB 到 0 延迟,一网打尽

57 阅读2分钟

打开 A 标签下单,B 标签实时同步购物车?登录退出一次搞定所有页?
别再 polling 服务器,今天把浏览器自带的 6 种“暗网通道”一次讲透。


📡 能力对照雷达图

方式容量延迟持久化同源限制推荐场景
BroadcastChannel 🔊无限0 ms实时同步
LocalStorage 🗃️5 MB~0 ms简单广播
SharedWorker ⚙️无限0 ms复杂计算
Service Worker 📲无限0 ms离线/推送
window.open + postMessage 🪟无限0 ms任意窗口
Cookie + StorageEvent 🍪4 KB~0 ms兼容老 IE

1. BroadcastChannel(最香)

// tab-A
const bc = new BroadcastChannel('cart');
bc.postMessage({ sku: 1001, count: 2 });

// tab-B
new BroadcastChannel('cart').onmessage = e =>
  console.log('收到购物车更新', e.data);
  • 同源即互联,0 延迟
  • 关闭页面即失效,适合做“实时仪表盘”

2. LocalStorage + StorageEvent(最轻量)

// tab-A
localStorage.setItem('login', 'Alice');

// tab-B
window.addEventListener('storage', e =>
  e.key === 'login' && console.log('用户切换', e.newValue)
);
  • 数据持久化,可跨会话
  • 只能监听其它标签写入,本页写入不触发

3. SharedWorker(共享线程)

// shared-worker.js
const ports = [];
onconnect = e => {
  const port = e.ports[0];
  ports.push(port);
  port.onmessage = msg =>
    ports.forEach(p => p.postMessage(msg.data));
};
// 任意标签
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = e => console.log(e.data);
worker.port.postMessage('hello');
  • 所有标签共享同一个线程,适合做集中计算
  • 需要 HTTPS(除 localhost)

4. Service Worker(离线王者)

// sw.js
self.addEventListener('message', e => {
  clients.matchAll().then(list =>
    list.forEach(c => c.postMessage(e.data))
  );
});
  • 支持推送 & 离线缓存
  • 注册一次,全站所有标签生效

5. window.open + postMessage(跨域也 OK)

// parent
const child = window.open('https://sub.shop.com');
child.postMessage({ type: 'sync-cart', data }, '*');

// child
window.addEventListener('message', e =>
  e.origin === 'https://main.shop.com' && updateCart(e.data)
);
  • 任意窗口/iframe 通信
  • 需手动管理引用 & 同源校验

6. Cookie + StorageEvent(老 IE 救生艇)

document.cookie = 'theme=dark;path=/';
window.addEventListener('storage', () => {
  const theme = /theme=([^;]+)/.exec(document.cookie)[1];
  applyTheme(theme);
});
  • 4 KB 容量,谨慎使用
  • 兼容 IE9+,无 BroadcastChannel 时代方案

🧩 实战组合:三屏联动购物车

// 实时 → BroadcastChannel
const bc = new BroadcastChannel('cart');
// 持久 → LocalStorage
function addCart(item) {
  const cart = JSON.parse(localStorage.getItem('cart') || '[]');
  cart.push(item);
  localStorage.setItem('cart', JSON.stringify(cart));
  bc.postMessage({ type: 'add', item });
}

效果:

  • 打开 A/B/C 三个标签 → 任意页添加商品,其余页 0 ms 同步
  • 刷新后 LocalStorage 恢复状态

🏁 总结一句话

  • 实时多页同步:BroadcastChannel
  • 跨会话持久:LocalStorage / Service Worker
  • 跨域窗口:postMessage + window.open
  • 老浏览器:Cookie

把这张通信地图贴在工位,下次需求评审直接甩给后端:“浏览器自带通道,不用轮询!”