解决前端多标签页通信:BroadcastChannel
大家好,我是 CC,在这里欢迎大家的到来~
背景
日常使用一些网站过程中,会发现当打开一个网站多个标签页时,当在其中一个标签页页面退出登录时,在其他标签页中还可以继续操作,这里就存在一个状态没有实时统一的问题;其后当操作发送请求时根据后端的登录校验情况会跳转到登录页,而这个操作滞后了。比如常用的 AI 网站 DeepSeek。
那如何在多标签页下进行状态的同步呢,这时候就要请出今天的“主人公”- BroadcastChannel。
来浅浅实践一下
使用起来很简单。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>BroadcastChannel</title>
</head>
<body><h1>BroadcastChannel</h1><script>const channel = new BroadcastChannel('my-channel');channel.postMessage('hello world');channel.onmessage = (event) => {console.log(event.data);}</script>
</body>
</html>
效果
在两个浏览器窗口中分别打开页面,当一个页面刷新后发送消息时,之前打开的相同页面收到了消息内容,但是当前页面没有收到消息内容。
注意
- 适用于同源的不同浏览器窗口、浏览器标签页、iframe之间互相通信
- 通过 message 事件进行广播
- 在监听该 channel 的所有 BroadcastChannel 对象上触发,但是不包含发送消息的对象
应用
举两个业务中会用到的例子:
同步登录状态
当多个页面处于未登录状态时,在其中一个页面上登录成功后,所有的页面都会收到消息,更新登录状态及页面路由。
// 登录状态管理
const authChannel = new BroadcastChannel('auth');// 登录成功后
function handleLogin(user) {localStorage.setItem('token', user.token);authChannel.postMessage({type: 'LOGIN_SUCCESS',user: user});
}// 监听登录状态
authChannel.onmessage = (event) => {switch (event.data.type) {case 'LOGIN_SUCCESS':updateUserInfo(event.data.user);break;case 'LOGOUT':clearUserData();redirectToLogin();break;}
};
同步页面设置
在多个 AI 对话页面场景下,在其中一个页面上个更改了 LLM 对话参数 Temperature 时,其余页面中相应参数也会更改,避免后知后觉**。**
// 应用配置同步
const configChannel = new BroadcastChannel('app-config');// 管理员更新配置
function updateAppSettings(settings) {configChannel.postMessage({type: 'SETTINGS_UPDATED',settings: settings});
}// 所有页面应用新配置
configChannel.onmessage = (event) => {if (event.data.type === 'SETTINGS_UPDATED') {applyNewSettings(event.data.settings);showNotification('配置已更新');}
};
同步业务数据
在多个页面对比商品时,在其中一个页面中加购商品后其余页面也会更新购物车列表,保证数据的一致性。
// 购物车同步
const cartChannel = new BroadcastChannel('cart');// 添加商品时通知其他标签页
function addToCart(product) {const cart = getCartFromStorage();cart.push(product);localStorage.setItem('cart', JSON.stringify(cart));cartChannel.postMessage({type: 'CART_UPDATE',cart: cart});
}// 监听购物车变化
cartChannel.onmessage = (event) => {if (event.data.type === 'CART_UPDATE') {updateCartUI(event.data.cart);}
};
对比其他方案
通信方式 | 适用场景 | 特点 |
BroadcastChannel | 同源标签页通信 | 简单易用,不支持跨域 |
LocalStorage 事件 | 简单数据同步 | 兼容性好,数据大小限制 |
SharedWorker | 复杂数据共享 | 功能强大,实现复杂 |
Window.postMessage | 跨域通信 | 需要引用目标窗口 |
总结
BroadcastChannel 非常适用于同源页面在多窗口、多标签页场景下的数据或状态同步,做到保持相同页面在同一时刻下数据的一致性。