浏览器多标签页通信方案
实现同源标签页之间数据通信的多种方法
问题
如何在浏览器的多个标签页之间实现数据通信?
解答
Broadcast Channel API
用于同源页面之间的广播通信,某个页面发送的消息会被其他页面监听到。
// 页面 A:创建频道并发送消息
const channel = new BroadcastChannel('my_channel');
channel.postMessage('Hello from Page A');
// 页面 B:监听消息
const channel = new BroadcastChannel('my_channel');
channel.onmessage = (event) => {
console.log('Received:', event.data);
};
注意:仅支持同源页面,无法跨域通信。
localStorage
利用浏览器多标签共享的存储空间实现通信(sessionStorage 是会话级的,每个标签独立)。
// 页面 A:写入数据
localStorage.setItem('message', JSON.stringify({ text: 'Hello', time: Date.now() }));
// 页面 B:监听变化
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
const data = JSON.parse(event.newValue);
console.log('Received:', data);
}
});
SharedWorker
可被多个同源 window 共享的 Worker 线程。
// 创建 shared-worker.js
self.addEventListener('connect', (event) => {
const port = event.ports[0];
port.onmessage = (e) => {
// 广播给所有连接的页面
port.postMessage(e.data);
};
});
// 页面中使用
const worker = new SharedWorker('shared-worker.js');
worker.port.start();
worker.port.postMessage('Hello');
worker.port.onmessage = (event) => {
console.log('Received:', event.data);
};
WebSocket
通过服务器中转实现全双工通信,支持跨域。
const ws = new WebSocket('ws://example.com');
ws.onopen = () => {
ws.send('Hello from this tab');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
postMessage
适用于有依赖关系的页面(如 window.open 打开的页面或 iframe 嵌入的页面)。
// 页面 A:打开页面 B
const pageB = window.open('https://example.com/pageB.html');
pageB.postMessage('Hello from A', 'https://example.com');
// 页面 B:接收并回复
window.addEventListener('message', (event) => {
if (event.origin !== 'https://example.com') return;
console.log('Received:', event.data);
// 回复消息
event.source.postMessage('Hello from B', event.origin);
});
postMessage 的第一个参数是消息内容(可序列化对象),第二个参数是目标源('/' 表示同源,'*' 表示所有页面)。
Cookie + 定时器
通过定时检查 Cookie 变化实现通信(不推荐,资源浪费)。
// 页面 A:轮询检查
let lastValue = document.cookie;
setInterval(() => {
const currentValue = document.cookie;
if (currentValue !== lastValue) {
console.log('Cookie changed');
lastValue = currentValue;
}
}, 1000);
// 页面 B:修改 Cookie
document.cookie = 'message=Hello';
关键点
- Broadcast Channel API 是最简单的同源通信方案,但兼容性需注意
- localStorage 配合 storage 事件可实现简单的跨标签通信
- postMessage 需要页面间有引用关系(window.open 或 iframe)
- WebSocket 可跨域通信,但需要服务器支持
- Cookie + 定时器方案性能差,不推荐使用
目录