javaScript

何跨标签页通信

# 1:BroadCast Channel - 对讲机频道

// 所有标签页加入同一个"频道"
const channel = new BroadcastChannel('shop_channel');

// 标签1发送消息
channel.postMessage({ action: 'addToCart', item: '可爱猫猫' });

// 标签2接收消息
channel.onmessage = event => {
    console.log('收到消息:', event.data);
    // 显示:"收到消息: {action: "addToCart", item: "可爱猫猫"}"
};

# 2:Service Worker - 隐形邮差

// 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('快递到啦!');

# 3:LocalStorage - 共享小本本

// 标签1写下留言
localStorage.setItem('message', '今晚吃火锅!');

// 标签2监听小本本变化
window.addEventListener('storage', event => {
    if (event.key === 'message') {
        console.log('新留言:', event.newValue);
    }
});

# 4:SharedWorker - 共享线程

// shared-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('大家好呀!');

# 5:window.open - 父子窗口说悄悄话

// 父窗口
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);
});

# 6:WebSocket - 双向通信

// 所有标签页连接同一个WebSocket
const socket = new WebSocket('wss://example.com/chat');

socket.onmessage = (event) => {
  console.log('服务器通知:', event.data);
};

// 发送消息
socket.send('标签1发来的消息');

# 7:SharedArrayBuffer - 共享内存

// 主线程
const buffer = new SharedArrayBuffer(1024);
const arr = new Int32Array(buffer);

// 可以传递给Worker
worker.postMessage({ buffer });

// Worker中修改
Atomics.store(arr, 0, 123); // 线程安全写入

# 实际项目选择建议

  • 1 先试试 BroadcastChannel(最简单)
  • 2 需要离线功能?上 Service Worker
  • 3 大量数据共享?SharedWorker 等着你
  • 4 要兼容 IE?只能用 localStorage 啦
上次更新: