# 跨页面通信的8种实现方案
## 1. localStorage/sessionStorage 事件监听
```javascript
// 页面A发送消息
localStorage.setItem('message', JSON.stringify({type: 'update', data: '新内容'}));
// 页面B监听变化
window.addEventListener('storage', (e) => {
if(e.key === 'message') {
const data = JSON.parse(e.newValue);
console.log('收到消息:', data);
}
});
特点:
- 同源策略限制
- 存储容量约5MB
- sessionStorage仅在当前会话有效
2. Broadcast Channel API
// 页面A
const bc = new BroadcastChannel('app_channel');
bc.postMessage({type: 'notification', content: '新消息'});
// 页面B
const bc = new BroadcastChannel('app_channel');
bc.onmessage = (e) => {
console.log('收到广播:', e.data);
};
优势:
- 支持任意同源页面通信
- 不需要中间存储
- 现代浏览器广泛支持
3. SharedWorker 共享线程
// worker.js
const ports = [];
onconnect = (e) => {
const port = e.ports[0];
ports.push(port);
port.onmessage = (e) => {
ports.forEach(p => {
if(p !== port) p.postMessage(e.data);
});
};
};
// 页面代码
const worker = new SharedWorker('worker.js');
worker.port.onmessage = (e) => {
console.log('收到共享消息:', e.data);
};
worker.port.postMessage('Hello');
适用场景:
- 需要长期保持的连接
- 多个页面需要共享状态
- 复杂的数据处理逻辑
4. window.postMessage
// 父窗口打开子窗口
const child = window.open('child.html');
// 父窗口发送消息
child.postMessage('父窗口消息', 'https://example.com');
// 子窗口接收
window.addEventListener('message', (e) => {
if(e.origin !== 'https://example.com') return;
console.log(e.data);
});
安全要点:
- 必须验证origin
- 可用于跨域通信
- 需要保持窗口引用
5. Service Worker + MessageChannel
// service-worker.js
self.addEventListener('message', (event) => {
event.ports[0].postMessage('SW应答:' + event.data);
});
// 页面代码
navigator.serviceWorker.controller.postMessage(
'页面消息',
[new MessageChannel().port2]
);
优势组合:
- 支持离线场景
- 可实现后台同步
- 消息通道双向通信
6. IndexedDB 共享数据库
// 页面A写入
const db = await openDB('msg_db', 1);
await db.put('messages', {id: 1, content: '新消息'});
// 页面B轮询检查
setInterval(async () => {
const db = await openDB('msg_db', 1);
const msg = await db.get('messages', 1);
if(msg) console.log(msg);
}, 1000);
适用场景:
- 需要持久化存储
- 大数据量通信
- 不要求实时性
7. Cookie 轮询
// 页面A设置cookie
document.cookie = `msg=${encodeURIComponent('cookie消息')}; path=/`;
// 页面B检查cookie
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if(parts.length === 2) return decodeURIComponent(parts.pop().split(';').shift());
}
setInterval(() => {
const msg = getCookie('msg');
if(msg) console.log(msg);
}, 500);
限制:
- 每个域名cookie数量有限
- 需要轮询不够高效
- 数据量受限(4KB左右)
8. WebSocket 服务器中转
// 公共WS服务
const ws = new WebSocket('wss://push.example.com');
// 页面A发送
ws.send(JSON.stringify({
type: 'broadcast',
room: 'room1',
data: 'WS消息'
}));
// 页面B接收
ws.onmessage = (e) => {
const msg = JSON.parse(e.data);
if(msg.room === 'room1') {
console.log