跨页面如何进行通信?有哪些方法?

72 阅读2分钟
# 跨页面通信的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