🎨 方案1:BroadCast Channel(对讲机频道)
🛠️ 方案2:Service Worker(隐形邮差)
📦 方案3:LocalStorage(共享小本本)
👨‍💻 方案4:Shared Worker(共享办公室)
🕵️‍♂️ 方案5-6:轮询侦查队(IndexedDB/Cookie)
👨‍👦 方案7:window.open(父子悄悄话)
🌐 方案8:WebSocket(专业电话线)
🧩 方案9:SharedArrayBuffer(共享黑板)


今天我们要去探索”跨标签页通信”这个神奇的乐园!🚀

🌟 开篇小剧场:为什么标签页要”聊天”?

想象你在网上商城:

标签1:浏览商品页
标签2:开着购物车

当你在标签1点击”加入购物车”,标签2的购物车数字应该立即+1!这就是标签页通信的魔力啦!✨


🎨 方案1:BroadCast Channel - 对讲机频道

 1const channel = new BroadcastChannel('shop_channel');
 2
 3
 4channel.postMessage({ action: 'addToCart', item: '可爱猫猫' });
 5
 6
 7channel.onmessage = (event) => {
 8  console.log('收到消息:', event.data); 
 9  
10};

📌 特点

就像一群人在同一个对讲机频道聊天
现代浏览器都支持(IE除外😅)
适合频繁通信


🛠️ 方案2:Service Worker - 隐形邮差

 1self.addEventListener('message', (event) => {
 2  
 3  self.clients.matchAll().then(clients => {
 4    clients.forEach(client => client.postMessage(event.data));
 5  });
 6});
 7
 8
 9navigator.serviceWorker.onmessage = (event) => {
10  console.log('邮差送来消息:', event.data);
11};
12
13
14navigator.serviceWorker.controller.postMessage('快递到啦!');

🎯 适用场景

PWA应用(比如离线可用的网页)
需要后台同步的场景


📦 方案3:LocalStorage - 共享小本本

 1localStorage.setItem('message', '今晚吃火锅!');
 2
 3
 4window.addEventListener('storage', (event) => {
 5  if (event.key === 'message') {
 6    console.log('新留言:', event.newValue);
 7  }
 8});

⚠️ 注意

当前标签页修改不会触发自己的监听
容量约5MB(能写很多小纸条啦)


👨‍💻 方案4:Shared Worker - 共享办公室

 1const ports = []; 
 2
 3onconnect = (e) => {
 4  const port = e.ports[0];
 5  ports.push(port);
 6  
 7  port.onmessage = (event) => {
 8    
 9    ports.forEach(p => p !== port && p.postMessage(event.data));
10  };
11};
12
13
14const worker = new SharedWorker('shared-worker.js');
15worker.port.onmessage = (event) => {
16  console.log('办公室通知:', event.data);
17};
18worker.port.postMessage('大家好呀!');

💡 比喻

就像多个标签页在一个共享办公室工作
通过中间的worker传递消息


🕵️‍♂️ 方案5-6:轮询侦查队(IndexedDB/Cookie)

 1setInterval(() => {
 2  db.get('message').then(val => {
 3    if (val !== lastMessage) {
 4      console.log('发现新消息:', val);
 5      lastMessage = val;
 6    }
 7  });
 8}, 1000);
 9
10
11setInterval(() => {
12  const msg = getCookie('message');
13  if (msg !== lastMsg) {
14    console.log('Cookie消息:', msg);
15    lastMsg = msg;
16  }
17}, 1000);

🚨 注意

像不断检查信箱的侦查员
不推荐高频使用(耗电耗资源)


👨‍👦 方案7:window.open - 父子窗口说悄悄话

 1const child = window.open('child.html');
 2child.postMessage('乖儿子', 'https://same-origin.com');
 3
 4
 5window.opener.postMessage('老爸好!', 'https://same-origin.com');
 6
 7
 8window.addEventListener('message', (event) => {
 9  if (event.origin !== 'https://same-origin.com') return;
10  console.log('收到:', event.data);
11});

🔒 安全第一

必须验证event.origin!
就像只接收认识的人的信件


🌐 方案8:WebSocket - 专业电话线

 1const socket = new WebSocket('wss://example.com/chat');
 2
 3socket.onmessage = (event) => {
 4  console.log('服务器通知:', event.data);
 5};
 6
 7
 8socket.send('标签1发来的消息');

🏆 优势

实时性最强
适合需要服务器参与的复杂场景


🧩 方案9:SharedArrayBuffer - 共享黑板(高级)

 1const buffer = new SharedArrayBuffer(1024);
 2const arr = new Int32Array(buffer);
 3
 4
 5worker.postMessage({ buffer });
 6
 7
 8Atomics.store(arr, 0, 123); 

🚧 注意

需要设置安全响应头
适合高性能计算


🎓 选择指南

方案适合场景难度实时性记忆口诀
BroadcastChannel简单现代应用⭐⭐⭐“对讲机聊天”
LocalStorage少量数据同步⭐⭐“共享小本本”
SharedWorker复杂数据共享⭐⭐⭐⭐⭐⭐“共享办公室”
Service WorkerPWA/离线应用⭐⭐⭐⭐⭐“隐形邮差”
WebSocket需要服务器参与⭐⭐⭐⭐⭐“专业电话线”
window.postMessage特定窗口通信⭐⭐⭐⭐⭐“父子悄悄话”

实际项目选择建议

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

个人笔记记录 2021 ~ 2025