瀏覽器悄悄上線了這個 API,大大簡化了跨瀏覽器標簽頁通信
過去,最常見的就是利用 localStorage 的 onstorage 事件監聽來處理跨瀏覽器標簽頁通信,但其本職是存儲,通信只是其副作用,且 API 不夠直觀。
現代瀏覽器已經為我們提供了一個專門為此場景設計的、更優雅、更高效的解決方案。
什么是 BroadcastChannel?
BroadcastChannel API 允許來自同源的瀏覽器不同上下文(如標簽頁、窗口、iframe)之間進行通信。
其核心特點是:同源限制、發布/訂閱模式且角色可以互換、基于消息事件對高效通信、支持復雜數據,無需手動序列化。
它的 API 非常簡潔,主要包含創建、發送、接收和關閉四個步驟。
1. 創建或加入一個頻道
要進行通信,首先需要創建一個 BroadcastChannel 實例,并給它指定一個唯一的頻道名稱。所有希望通信的頁面都必須使用相同的頻道名稱。
// 創建一個名為 'user_status_channel' 的頻道
const channel = new BroadcastChannel('user_status_channel');
如果名為 user_status_channel 的頻道已存在,這行代碼會加入該頻道;如果不存在,則會創建它。
2. 發送消息
創建實例后,使用 postMessage() 方法向頻道廣播消息。所有監聽該頻道的其他標簽頁都會收到此消息。
postMessage() 的強大之處在于它可以發送各種復雜的數據結構,包括對象、數組、Map、Set、File 對象等,瀏覽器會自動處理序列化和反序列化。
3. 接收消息
通過監聽 message 事件來接收廣播。事件對象 event 中包含了我們最關心的 data 屬性,也就是發送方傳遞的消息。
channel.onmessage = (event) => {
console.log('收到消息:', event.data);
// 根據消息內容執行相應操作
if (event.data && event.data.type === 'login') {
updateUIForLogin(event.data.user);
} else if (event.data && event.data.type === 'logout') {
updateUIForLogout();
}
};
// 也可以使用 addEventListener
// channel.addEventListener('message', (event) => { ... });
4. 關閉頻道
當頁面不再需要接收或發送消息時(例如,在組件卸載或頁面關閉時),應該調用 close() 方法來關閉頻道,以釋放資源。
// 當組件銷毀或頁面關閉時
window.onunload = () => {
channel.close();
};
// 在 React 或 Vue 等框架中,可以在組件的卸載生命周期函數中調用
// useEffect(() => {
// return () => channel.close();
// }, []);
BroadcastChannel API 是實現同源跨標簽頁通信的現代化標準方案,具有簡潔的 API、強大的功能和優秀的性能,完美地解決了 localStorage hack 方案的各種痛點。
至于兼容性,只要不用 IE 就行。