打开 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
把这张通信地图贴在工位,下次需求评审直接甩给后端:“浏览器自带通道,不用轮询!”