各个 發表於 2025-4-24 16:39:00

如何跨标签页通信

<h1 data-id="heading-0">🧑‍💻 写在开头</h1>
<p>点赞 + 收藏 === 学会🤣🤣🤣</p>
<h2 data-id="heading-0">开篇小剧场:为什么标签页要"聊天"?</h2>
<p>想象你在网上商城:</p>
<p>标签1:浏览商品页<br>标签2:开着购物车</p>
<p>当你在标签1点击"加入购物车",标签2的购物车数字应该立即+1!这就是标签页通信的魔力啦!✨</p>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">🎨 方案1:BroadCast Channel(对讲机频道)
🛠️ 方案2:Service Worker(隐形邮差)
📦 方案3:LocalStorage(共享小本本)
👨‍💻 方案4:Shared Worker(共享办公室)
🕵️‍♂️ 方案5-6:轮询侦查队(IndexedDB/Cookie)
👨‍👦 方案7:window.open(父子悄悄话)
🌐 方案8:WebSocket(专业电话线)
🧩 方案9:SharedArrayBuffer(共享黑板)</pre>
</div>
<h2 data-id="heading-1">🎨 方案1:BroadCast Channel - 对讲机频道</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;collapse:true;;gutter:true;">// 所有标签页加入同一个"频道"
const channel = new BroadcastChannel('shop_channel');

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

// 标签2接收消息
channel.onmessage = (event) =&gt; {
console.log('收到消息:', event.data);
// 显示:"收到消息: {action: "addToCart", item: "可爱猫猫"}"
};</pre>
</div>
<p>📌 特点:</p>
<p>就像一群人在同一个对讲机频道聊天<br>现代浏览器都支持(IE除外😅)<br>适合频繁通信</p>
<hr>
<h2 data-id="heading-2">🛠️ 方案2:Service Worker - 隐形邮差</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;collapse:true;;gutter:true;">// service-worker.js
self.addEventListener('message', (event) =&gt; {
// 告诉所有标签页
self.clients.matchAll().then(clients =&gt; {
    clients.forEach(client =&gt; client.postMessage(event.data));
});
});

// 标签页代码
navigator.serviceWorker.onmessage = (event) =&gt; {
console.log('邮差送来消息:', event.data);
};

// 发送消息
navigator.serviceWorker.controller.postMessage('快递到啦!');</pre>
</div>
<p>🎯 适用场景:</p>
<p>PWA应用(比如离线可用的网页)<br>需要后台同步的场景</p>
<hr>
<h2 data-id="heading-3">📦 方案3:LocalStorage - 共享小本本</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;collapse:true;;gutter:true;">// 标签1写下留言
localStorage.setItem('message', '今晚吃火锅!');

// 标签2监听小本本变化
window.addEventListener('storage', (event) =&gt; {
if (event.key === 'message') {
    console.log('新留言:', event.newValue);
}
});</pre>
</div>
<p>⚠️ 注意:</p>
<p>当前标签页修改不会触发自己的监听<br>容量约5MB(能写很多小纸条啦)</p>
<hr>
<h2 data-id="heading-4">👨‍💻 方案4:Shared Worker - 共享办公室</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;collapse:true;;gutter:true;">// shared-worker.js
const ports = []; // 连接的所有标签页

onconnect = (e) =&gt; {
const port = e.ports;
ports.push(port);

port.onmessage = (event) =&gt; {
    // 广播给其他同事
    ports.forEach(p =&gt; p !== port &amp;&amp; p.postMessage(event.data));
};
};

// 标签页代码
const worker = new SharedWorker('shared-worker.js');
worker.port.onmessage = (event) =&gt; {
console.log('办公室通知:', event.data);
};
worker.port.postMessage('大家好呀!');</pre>
</div>
<p>💡 比喻:</p>
<p>就像多个标签页在一个共享办公室工作<br>通过中间的worker传递消息</p>
<hr>
<h2 data-id="heading-5">🕵️‍♂️ 方案5-6:轮询侦查队(IndexedDB/Cookie)</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 方案5:IndexedDB轮询
setInterval(() =&gt; {
db.get('message').then(val =&gt; {
    if (val !== lastMessage) {
      console.log('发现新消息:', val);
      lastMessage = val;
    }
});
}, 1000);

// 方案6:Cookie轮询
setInterval(() =&gt; {
const msg = getCookie('message');
if (msg !== lastMsg) {
    console.log('Cookie消息:', msg);
    lastMsg = msg;
}
}, 1000);</pre>
</div>
<p>🚨 注意:</p>
<p>像不断检查信箱的侦查员<br>不推荐高频使用(耗电耗资源)</p>
<hr>
<h2 data-id="heading-6">👨‍👦 方案7:window.open - 父子窗口说悄悄话</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 父窗口
const child = window.open('child.html');
child.postMessage('乖儿子', 'https://same-origin.com');

// 子窗口
window.opener.postMessage('老爸好!', 'https://same-origin.com');

// 两边都要监听
window.addEventListener('message', (event) =&gt; {
if (event.origin !== 'https://same-origin.com') return;
console.log('收到:', event.data);
});</pre>
</div>
<p>🔒 安全第一:</p>
<p>必须验证event.origin!<br>就像只接收认识的人的信件</p>
<hr>
<h2 data-id="heading-7">🌐 方案8:WebSocket - 专业电话线</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 所有标签页连接同一个WebSocket
const socket = new WebSocket('wss://example.com/chat');

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

// 发送消息
socket.send('标签1发来的消息');</pre>
</div>
<p>🏆 优势:</p>
<p>实时性最强<br>适合需要服务器参与的复杂场景</p>
<hr>
<h2 data-id="heading-8">🧩 方案9:SharedArrayBuffer - 共享黑板(高级)</h2>
<div class="cnblogs_Highlighter">
<pre class="brush:bash;gutter:true;">// 主线程
const buffer = new SharedArrayBuffer(1024);
const arr = new Int32Array(buffer);

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

// Worker中修改
Atomics.store(arr, 0, 123); // 线程安全写入</pre>
</div>
<p>🚧 注意:</p>
<p>需要设置安全响应头<br>适合高性能计算</p>
<hr>
<h2 data-id="heading-9">🎓 选择指南</h2>
<p><img src="https://img2024.cnblogs.com/blog/2149129/202504/2149129-20250424163839858-787248883.png" alt="" loading="lazy"></p>
<div>
<div>
<p><strong>实际项目选择建议</strong>:</p>
<p>1 先试试BroadcastChannel(最简单)<br>
2 需要离线功能?上Service Worker <br>
3 大量数据共享?SharedWorker等着你 <br>
4 要兼容IE?只能用localStorage啦</p>
<p>记住:没有最好的方案,只有最合适的方案!就像选择工具一样,用对场景最重要~</p>

</div>
<h3 id="tid-D8HBxE">如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。</h3>
<p><img src="https://img2024.cnblogs.com/blog/2149129/202501/2149129-20250122165814748-630765389.png" alt="" loading="lazy"></p>
</div><br><br>
来源:https://www.cnblogs.com/smileZAZ/p/18844890
頁: [1]
查看完整版本: 如何跨标签页通信