【JS Web API】BroadcastChannel 跨窗口通信的原生解决方案

2026-04-28 19:03:39

BroadcastChannel API 允许跨标签页(访问相同的网站)进行通信,与之前介绍的 Storage Event 类似,可解决如下问题:

  1. 多标签页同步登入/登出状态:当用户在任意标签页登录或退出时,其它所有已打开的页面能实时获取状态更新;
  2. 购物车实时更新:当用户在一个商品页面增删购物车商品时,其它已打开的商品页面能立刻反映出最新的购物车内容;
  3. 实时主题切换:当用户在任一页面切换(例如亮色/暗色)主题时,所有其它同源页面的主题效果会立即同步。

使用起来非常简单,核心思想类似于一个聊天室,通过名称加入聊天室,在聊天室中发送一条消息,所有在此聊天室里的其它连接都能收到这条消息。

加入聊天室并发送消息:

// 加入聊天室,参数是聊天室名称是自定义的
const channel = new BroadcastChannel('my_channel')

// 发送一条消息,消息可以字符串,数组,对象字面量,Blob 等都可以
channel.postMessage('hello world')

加入聊天室并接收消息,两种方式接收信息,我一般选择 addEventListener(‘message’)。

// 加入聊天室,参数是聊天室名称是自定义的
const channel = new BroadcastChannel('my_channel')

// 方式一:为 onmessage 属性赋值
channel.onmessage = function(event) {
  console.log('收到消息:', event.data)
}

// 方式二:使用事件监听器(推荐,便于灵活管理)
channel.addEventListener('message', function(event) {
  console.log('收到消息:', event.data)
})

退出聊天室:

// 加入聊天室,参数是聊天室名称是自定义的
const channel = new BroadcastChannel('my_channel')
// 退出聊天室
channel.close()

理论知识就这些,让我们看一个在 React 中的实例

将下列代码复制到 React 页面中,在两个独立的浏览器标签页中打开同一个页面。初始背景都为白色,在第一个标签页点击按钮改变颜色,切换到第二个标签页可以看到背景颜色同步更改了。

import { useEffect, useState } from "react"

export function App() {
  const [ theme, setTheme ] = useState<string>('white')

  useEffect(() => {
    const channel = new BroadcastChannel('theme-color')

    const handleMessage = (event: MessageEvent) => {
      if (!event.data) return
      setTheme(event.data)
    }
    
    // 注册监听器接收频道消息
    channel.addEventListener('message', handleMessage)

    return () => {
      // 组件卸载时,清理事件监听器并关闭频道连接
      channel.removeEventListener('message', handleMessage)
      channel.close()
    }
  }, [])

  const updateThemeAndBroadcast = (color: string) => {
    setTheme(color)
    // 将主题变更广播到所有连接到“theme-color”频道的页面
    const channel = new BroadcastChannel('theme-color')
    channel.postMessage(color)
    channel.close() // 发送后立即关闭临时通道,或复用单一通道实例
  }

  return (
    <div style={{ backgroundColor: theme, minHeight: '100vh' }}>
      <button onClick={() => updateThemeAndBroadcast('red')}>Red</button>
      <button onClick={() => updateThemeAndBroadcast('green')}>Green</button>
    </div>
  )
}

export default App

Boardcast Channel 与 Redux、Zustand 等状态管理器有什么区别?

状态管理器 (Redux/Zustand) 可以做到在同一个标签页内不同页面之间共享数据,数据存储在单一标签页的运行时内存中,是没办法跨标签页共享数据的,上面的例子在不同标签页之间同步更改页面背景颜色使用状态管理是做不到的。

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: