跨标签页通信
Broadcast Channel API
js
// 所有标签页加入同一个"频道"
const channel = new BroadcastChannel('shop_channel');
// 标签1发送消息
channel.postMessage({action: 'addToCart', item: '可爱猫猫'});
// 标签2接收消息
channel.onmessage = (event) => {
console.log('收到消息:', event.data);
// 显示:"收到消息: {action: "addToCart", item: "可爱猫猫"}"
};
就像一群人在同一个对讲机频道聊天 现代浏览器都支持(IE除外😅) 适合频繁通信
Service Worker
js
// service-worker.js
self.addEventListener('message', (event) => {
// 告诉所有标签页
self.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage(event.data));
});
});
// 标签页代码
navigator.serviceWorker.onmessage = (event) => {
console.log('邮差送来消息:', event.data);
};
// 发送消息
navigator.serviceWorker.controller.postMessage('快递到啦!');
PWA应用(比如离线可用的网页) 需要后台同步的场景
LocalStorage
js
// 标签1写下留言
localStorage.setItem('message', '今晚吃火锅!');
// 标签2监听小本本变化
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
console.log('新留言:', event.newValue);
}
});
当前标签页修改不会触发自己的监听 容量约5MB(能写很多小纸条啦)
Shaded Worker
js
const ports = []; // 连接的所有标签页
onconnect = (e) => {
const port = e.ports[0];
ports.push(port);
port.onmessage = (event) => {
// 广播给其他同事
ports.forEach(p => p !== port && p.postMessage(event.data));
};
};
// 标签页代码
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = (event) => {
console.log('办公室通知:', event.data);
};
worker.port.postMessage('大家好呀!');
轮询扫描 IndexedDB/Cookie
js
// 方案5:IndexedDB轮询
setInterval(() => {
db.get('message').then(val => {
if (val !== lastMessage) {
console.log('发现新消息:', val);
lastMessage = val;
}
});
}, 1000);
// 方案6:Cookie轮询
setInterval(() => {
const msg = getCookie('message');
if (msg !== lastMsg) {
console.log('Cookie消息:', msg);
lastMsg = msg;
}
}, 1000);
window.open 父子窗口对话
js
// 父窗口
const child = window.open('child.html');
child.postMessage('乖儿子', 'https://same-origin.com');
// 子窗口
window.opener.postMessage('老爸好!', 'https://same-origin.com');
// 两边都要监听
window.addEventListener('message', (event) => {
if (event.origin !== 'https://same-origin.com') return;
console.log('收到:', event.data);
});
必须验证 event.origin
只能接收认识的人的信息
WebSocket
js
// 所有标签页连接同一个WebSocket
const socket = new WebSocket('wss://example.com/chat');
socket.onmessage = (event) => {
console.log('服务器通知:', event.data);
};
// 发送消息
socket.send('标签1发来的消息');
实时性最强 适合需要服务器参与的复杂场景
SharedArrayBuffer
js
// 主线程
const buffer = new SharedArrayBuffer(1024);
const arr = new Int32Array(buffer);
// 可以传递给Worker
worker.postMessage({buffer});
// Worker中修改
Atomics.store(arr, 0, 123); // 线程安全写入
需要设置安全响应头 适合高性能计算
总结
方案 | 适合场景 | 难度 | 实时性 | 记忆口诀 |
---|---|---|---|---|
BroadcastChannel | 简单现代应用 | ⭐⭐ | ⭐⭐⭐⭐ | "对讲机聊天" |
LocalStorage | 少量数据同步 | ⭐ | ⭐⭐⭐ | "共享小本本" |
SharedWorker | 复杂数据共享 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐⭐ | "共享办公室" |
Service Worker | PWA/离线应用 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | "隐形邮差" |
WebSocket | 需要服务器参与 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | "专业电话线" |
window.postMessage | 特定窗口通信 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | "父子悄悄话" |