🎨 方案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 Worker | PWA/离线应用 | ⭐⭐ | ⭐⭐⭐ | “隐形邮差” |
WebSocket | 需要服务器参与 | ⭐⭐ | ⭐⭐⭐ | “专业电话线” |
window.postMessage | 特定窗口通信 | ⭐⭐ | ⭐⭐⭐ | “父子悄悄话” |
实际项目选择建议:
1 先试试BroadcastChannel(最简单)
2 需要离线功能?上Service Worker
3 大量数据共享?SharedWorker等着你
4 要兼容IE?只能用localStorage啦
个人笔记记录 2021 ~ 2025