跨页面通信
大约 2 分钟
跨页面通信详解
跨页面通信是指在不同页面、窗口或标签页之间进行数据交换和消息传递的技术。以下是主要的跨页面通信方式:
1. Window.postMessage()
window.postMessage() 是最常用的跨页面通信方式,适用于不同源的页面间通信。
示例:
// 发送消息的页面
const otherWindow = window.open('https://example.com/target.html');
otherWindow.postMessage('Hello from opener', 'https://example.com');
// 接收消息的页面
window.addEventListener('message', (event) => {
if (event.origin !== 'https://sender-domain.com') return;
console.log('Received message:', event.data);
});2. localStorage/sessionStorage 事件监听
通过监听 storage 事件实现跨标签页通信。
示例:
// 页面A - 设置数据
localStorage.setItem('message', 'Hello World');
// 页面B - 监听变化
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
console.log('Received:', event.newValue);
}
});3. SharedWorker
SharedWorker 允许多个浏览上下文连接到同一个 worker 进行通信。
示例:
// 主页面
const worker = new SharedWorker('shared-worker.js');
worker.port.postMessage('Hello SharedWorker');
worker.port.onmessage = (event) => {
console.log('Received:', event.data);
};
// shared-worker.js
const connections = [];
self.onconnect = (event) => {
const port = event.ports[0];
connections.push(port);
port.onmessage = (e) => {
// 广播消息给所有连接
connections.forEach(conn => {
if (conn !== port) {
conn.postMessage(e.data);
}
});
};
};4. BroadcastChannel API
现代浏览器提供的广播通信机制,适用于同源页面。
示例:
// 页面A
const channel = new BroadcastChannel('my-channel');
channel.postMessage({ type: 'greeting', message: 'Hello!' });
// 页面B
const channel = new BroadcastChannel('my-channel');
channel.onmessage = (event) => {
console.log('Received:', event.data.message);
};5. Cookie + 轮询
通过共享 cookie 并定时检查变化实现通信(不推荐)。
示例:
// 发送方
document.cookie = "message=Hello; path=/";
// 接收方
let lastMessage = "";
setInterval(() => {
const cookies = document.cookie.split(';');
const messageCookie = cookies.find(c => c.trim().startsWith('message='));
if (messageCookie) {
const message = messageCookie.split('=')[1];
if (message !== lastMessage) {
console.log('New message:', message);
lastMessage = message;
}
}
}, 1000);6. WebSocket
通过 WebSocket 服务器中转消息实现多页面通信。
示例:
// 页面A和B都连接到同一个WebSocket服务器
const socket = new WebSocket('ws://localhost:8080');
socket.onopen = () => {
// 发送消息
socket.send(JSON.stringify({
type: 'broadcast',
data: 'Hello from page'
}));
};
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message.data);
};使用场景对比
| 方式 | 同源限制 | 浏览器兼容性 | 实时性 | 适用场景 |
|---|---|---|---|---|
| postMessage | 无 | 高 | 高 | iframe、窗口间通信 |
| storage事件 | 同源 | 高 | 高 | 同域标签页通信 |
| SharedWorker | 同源 | 中 | 高 | 复杂后台任务 |
| BroadcastChannel | 同源 | 中 | 高 | 简单广播通信 |
| Cookie轮询 | 同域 | 高 | 低 | 兼容老浏览器 |
| WebSocket | 无 | 高 | 高 | 实时多端通信 |
选择合适的跨页面通信方式需要根据具体的应用场景、浏览器兼容性要求和安全需求来决定。