动态

详情 返回 返回

如何跨標籤頁通信 - 动态 详情

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

開篇小劇場:為什麼標籤頁要"聊天"?

想象你在網上商城:

標籤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啦

記住:沒有最好的方案,只有最合適的方案!就像選擇工具一樣,用對場景最重要~

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。

user avatar yqyx36 头像 woniuseo 头像 assassin 头像 aser1989 头像 huanjinliu 头像 tonyyoung 头像 wojiaocuisite 头像 everfind 头像 onlythinking 头像 neronero 头像 shoyuf 头像 guisijun 头像
点赞 15 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.