🧑💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣
開篇小劇場:為什麼標籤頁要"聊天"?
想象你在網上商城:
標籤1:瀏覽商品頁
標籤2:開着購物車
當你在標籤1點擊"加入購物車",標籤2的購物車數字應該立即+1!這就是標籤頁通信的魔力啦!✨
🎨 方案1:BroadCast Channel(對講機頻道) 🛠️ 方案2:Service Worker(隱形郵差) 📦 方案3:LocalStorage(共享小本本) 👨💻 方案4:Shared Worker(共享辦公室) 🕵️♂️ 方案5-6:輪詢偵查隊(IndexedDB/Cookie) 👨👦 方案7:window.open(父子悄悄話) 🌐 方案8:WebSocket(專業電話線) 🧩 方案9:SharedArrayBuffer(共享黑板)
🎨 方案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: "可愛貓貓"}"
};
📌 特點:
就像一羣人在同一個對講機頻道聊天
現代瀏覽器都支持(IE除外😅)
適合頻繁通信
🛠️ 方案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('快遞到啦!');
🎯 適用場景:
PWA應用(比如離線可用的網頁)
需要後台同步的場景
📦 方案3:LocalStorage - 共享小本本
// 標籤1寫下留言
localStorage.setItem('message', '今晚吃火鍋!');
// 標籤2監聽小本本變化
window.addEventListener('storage', (event) => {
if (event.key === 'message') {
console.log('新留言:', event.newValue);
}
});
⚠️ 注意:
當前標籤頁修改不會觸發自己的監聽
容量約5MB(能寫很多小紙條啦)
👨💻 方案4:Shared Worker - 共享辦公室
// 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('大家好呀!');
💡 比喻:
就像多個標籤頁在一個共享辦公室工作
通過中間的worker傳遞消息
🕵️♂️ 方案5-6:輪詢偵查隊(IndexedDB/Cookie)
// 方案5:IndexedDB輪詢
setInterval(() => {
db.get('message').then(val => {
if (val !== lastMessage) {
console.log('發現新消息:', val);
lastMessage = val;
}
});
}, 1000);
// 方案6:Cookie輪詢
setInterval(() => {
const msg = getCookie('message');
if (msg !== lastMsg) {
console.log('Cookie消息:', msg);
lastMsg = msg;
}
}, 1000);
🚨 注意:
像不斷檢查信箱的偵查員
不推薦高頻使用(耗電耗資源)
👨👦 方案7: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);
});
🔒 安全第一:
必須驗證event.origin!
就像只接收認識的人的信件
🌐 方案8:WebSocket - 專業電話線
// 所有標籤頁連接同一個WebSocket
const socket = new WebSocket('wss://example.com/chat');
socket.onmessage = (event) => {
console.log('服務器通知:', event.data);
};
// 發送消息
socket.send('標籤1發來的消息');
🏆 優勢:
實時性最強
適合需要服務器參與的複雜場景
🧩 方案9: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啦
記住:沒有最好的方案,只有最合適的方案!就像選擇工具一樣,用對場景最重要~