解决前端多标签页通信:BroadcastChannel

大家好,我是 CC,在这里欢迎大家的到来~

背景

日常使用一些网站过程中,会发现当打开一个网站多个标签页时,当在其中一个标签页页面退出登录时,在其他标签页中还可以继续操作,这里就存在一个状态没有实时统一的问题 ;其后当操作发送请求时根据后端的登录校验情况会跳转到登录页,而这个操作滞后了。比如常用的 AI 网站 DeepSeek。

那如何在多标签页下进行状态的同步呢,这时候就要请出今天的"主人公"- BroadcastChannel。

来浅浅实践一下

使用起来很简单。

html 复制代码
<!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 对象上触发,但是不包含发送消息的对象

应用

举两个业务中会用到的例子:

同步登录状态

当多个页面处于未登录状态时,在其中一个页面上登录成功后,所有的页面都会收到消息,更新登录状态及页面路由。

js 复制代码
// 登录状态管理
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 时,其余页面中相应参数也会更改,避免后知后觉**。**

js 复制代码
// 应用配置同步
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('配置已更新');
  }
};

同步业务数据

在多个页面对比商品时,在其中一个页面中加购商品后其余页面也会更新购物车列表,保证数据的一致性。

js 复制代码
// 购物车同步
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 非常适用于同源页面在多窗口、多标签页场景下的数据或状态同步,做到保持相同页面在同一时刻下数据的一致性。

相关推荐
LucianaiB2 小时前
【元宝搜索开发者征文大赛】AI时代,学得慢就不用学?用元宝搜索打造一个教程保质期,确保每一个教程符合你的现状
前端·人工智能·ai编程
excel2 小时前
JavaScript 对象池:减少高频对象创建与 GC 压力
前端
陈随易4 小时前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
子兮曰5 小时前
Chrome 权限元素实战:144 与 151 的渐进增强写法
前端·javascript·chrome
IT_陈寒6 小时前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
强尼银手6 小时前
我花一天做了个格斗游戏原型,判定全对,然后被「美术」劝退了
前端·javascript
石小石Orz6 小时前
AI 正在蚕食我们的编码能力
前端·后端·算法
陈随易6 小时前
专注飞机 FocusFlight,两个人把番茄钟做成了一趟航班
前端·后端·程序员
总要学点什么7 小时前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质
10share7 小时前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js