news 2026/5/1 9:17:02

浏览器跨标签页通信方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
浏览器跨标签页通信方案

应用场景:

  • 状态同步:多标签页之间同步数据,比如同步设备展示状态,同步数据信息。
  • 消息通知:通知其余标签页执行动作,比如说跳转其他页面,完成后,通知打开页面执行状态变更或刷新灯操作。
  • 隐私数据通信:基于加壳客户端,实现 H5 页面之间的本地通信机制,不经过网络层传输,还根据随机加密值实现跨权限式加密信道。

实现场景:

  • 需要跨域:Websocket、父子窗口。
  • 无需跨域:LocalStorage、SharedWorker、BroadcastChannel。

LocalStroage

利用同域下 LocalStorage 共享策略。

  • 实现跨标签页的信息同步。
  • 实现简单。

存在问题:

  • LocalStorage 有 5MB 大小限制,需要注意消息限制问题。

使用:

  1. A 页面监听storage事件。
  2. B 页面通过调用 LocalStorage 方法,触发事件,传给 A 页面进行使用
    • 通过获取e.newValue变化即可得知当前的传送的消息。
    • 当执行removeItem时,e.newValue会变为 null。
    • 通过e.url判断消息是否为自己发出,避免重复处理,或者监听消息来源。
// A 页面window.addEventListener('storage',(e)=>{console.log(e.key)// keyconsole.log(e.oldValue)// 旧值console.log(e.newValue)// 新值,即设置的值console.log(e.storageArea)// 被操作的 storage 对象console.log(e.url)// 文档改变的对象地址来源})// B 页面window.LocalStorage.setItem('xx','xxx')window.LocalStorage.removeItem('xxx','xxx')

SharedWorker

基于共享线程来完成通信,是独立于主线程的后台共享线程。
SharedWorker 本身承载业务共享逻辑,底层通信手段基于MessagePort实现。

  • 通过port通信降低主线程和 Shared Worker 的耦合度。
  • 生命周期和连接的主线程相关,主线程全部释放,SharedWorker 也会终止(可能会等待异步任务执行完成,但是每测试出来)。
  • 可能异常情况:
    • SecurityError:不能正常启动 Shraed Worker。
    • NetworkError:Shared Worker 不是application/json格式。
    • SyntaxError:URL 无法解析。

存在问题:

  • 兼容性问题,很多移动端浏览器不支持。
  • 增加请求和维护成本,定义额外的 js 文件。
  • 调试困难,需要通过chrome://inspect#workers界面查看调试信息。

使用:

主线程:

  1. 连接 SharedWorker。
  2. 通过shareWorker.port.postMessage向所有连接的页面发送消息。
  3. 通过shareWorker.port.onmessage接收发来的消息。
// 页面内(主线程)constshareWorker=newShareWorker('share-worker.js')shareWorker.port.onmessage=(e)=>{const{type,data}=e.dataif(type==='BROADCAST'){// 处理逻辑}}// 处理连接错误worker.port.onerror=function(error){console.error("Shared Worker 错误:",error);};// 显示激活shareWorker.port.start()functionsendMessage(){shareWorker.port.postMessage({type:'MESSAGE',data:{...}})}functiondisconnect(){shareWorker.port.postMessage({type:'DISCONNECT'})shareWorker.port.close()}

shared worker文件:

  1. 通过self.onconnect监听连接事件,只要完成初始化就会触发。
  2. 使用 Set 集合connections存储端口,支持 O(1) 操作消耗。
  3. 操作:
    • 通过port.onmessage监听任一主线程发来的消息,遍历connections广播消息。
    • 在使用完成时,通过port.close关闭端口并清除端口在connections中的缓存,一定要清除连接,避免出现缓存端口导致广播无效端口的情况出现。
    • port.start用于触发端口激活,调用不会触发什么内容,但是部分浏览器不调用可能会阻塞消息发送。
// share-worker.js (share Worker线程)// 通过 connections 管理端口constconnections=newSet();// 消息广播functionbroadcast(){connections.forEach(p=>{// 排除自身if(p!==port){p.postMessage({type:'BROADCAST',data:`${data}`});}});}functiondisconnect(port){connections.delete(port);port.close();// 关闭端口}self.onconnect=(e)=>{// 1. 读取端口:自动去重constport=e.ports[0];connections.add(port);// 2. 监听消息port.onmessage=(e)=>{const{type,data}=e.data;switch(type){case'MESSAGE':console.log('收到主线程消息:',data);// 广播给所有连接的主线程broadcast(data,port)break;case'DISCONNECT':disconnect(port)break;}};// 3. 监听端口错误/关闭,自动清理无效端口port.onerror=(err)=>{console.log('端口错误:',err);connections.delete(port);};// 显示激活端口(部分浏览器需显式调用)port.start();};

Brocastchannel

支持同源下跨标签页通信方案,适用于广播消息方案。

  • 创建频道名称,只要在同个频道名称下的标签,都能接收广播消息。
  • 无需像 SharedWorker 那样遍历广播,直接发送即可。
  • 实现简单,几行代码即可搞定。

存在问题:

  • 2022 年才稳定的 API ,需要考虑下兼容性问题。
  • 无法控制广播域,需要通过多频道来区分广播形式,或者通过标识符判断要处理消息的页面。

使用:

  • 通过new BroadcastChannel(channelName)创建频道。
  • 通过监听message来监听广播消息。
  • 通过channel.postMessage()发送消息。
constbroadcastChannel=newBroadcastChannel("channel");// 接收其他同频道的广播消息broadcastChannel.addEventListener("message",(e)=>{const{type,data}=e.data});// 为同频道广播消息broadcastChannle.postMessage({type:'message',data})

父子窗口

当使用window.open()打开窗口,可以通过父子窗口执行通信。

  • 利用 **浏览器窗口句柄(Window Handle)**和消息传递 支持了父子通信。
  • 可以使用父窗口作为中间层,实现各个子窗口的流通性以及广播功能。
  • 兼容性好。

存在问题:

  • 需要窗口之间存在父子引用关系。
  • 需要额外维护子窗口的引用信息。

使用:

  1. 父窗口通过window.open打开子窗口,同时保留子窗口的引用。
  2. 基于window.name区分子窗口,便于后续跨子窗口通信。
  3. 监听各自windowmessage事件实现通信 。
  4. 父窗口通过child.postMessage()发送消息,子窗口通过window.opener.postMessage()回复消息,如果要跨域,可以通过 postMessage 第二参数指定目标源,*代表向所有源发送消息。
// 父窗口constchild=window.open('/some-page')// 给子窗口定义唯一id,便于通信child.name='win_'+id()window.addEventlistener('message',()=>{// 监听子窗口传递的消息})// 在子窗口 /some-page 页面// 发送数据到父窗口window.opener.postMessage({type:'message',name:window.name,data})window.addEventlistener('message',()=>{// 监听父窗口传递的消息})

Websocket

通过 websocket ,以服务端做中转,实现跨域通信方案。

  • 支持跨域,同时支持跨浏览器跨设备。
  • 可以结合其他跨标签方案,实现复用 websocket 连接的操作。

存在问题

  • 需要服务端支持,实现较为复杂。

MessageChannel

这个方案还是比较常用在 iframe 跨域通信机制中,仅记录。

MessageChannel 本质也是依赖 MessagePort 来实现的通信机制,本质和 SharedWorker 一样。
如果实现跨标签页通讯,需要有中间人且支持结构化克隆算法来协助传递 port 端口信息。

参考内容

  • Window: postMessage() 方法 - Web API | MDN - MDN 文档
  • BroadcastChannel - Web API | MDN
  • SharedWorker - Web API | MDN
  • MessagePort - Web API | MDN
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 5:04:03

ThinkPHP开发效率提升300%的秘诀

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 生成一个完整的ThinkPHP企业官网CMS系统,包含:1.多语言支持 2.可视化页面构建器 3.SEO优化功能 4.表单收集系统 5.访客统计模块。要求使用最新的ThinkPHP 8.…

作者头像 李华
网站建设 2026/4/30 19:01:24

30分钟用os.path.splitext打造文件分析工具原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 快速开发一个文件分析工具原型,功能包括:1. 统计目录下各类扩展名的文件数量;2. 找出无扩展名文件;3. 识别重复扩展名。要求&#xf…

作者头像 李华
网站建设 2026/4/29 12:07:01

科学图表色彩革命:Paul Tol离散彩虹系统的完整指南与实战应用

科学图表色彩革命:Paul Tol离散彩虹系统的完整指南与实战应用 【免费下载链接】SciencePlots garrettj403/SciencePlots: SciencePlots 是一个面向科研人员的Matplotlib样式库,旨在创建符合科学出版规范且专业美观的数据图表。该库包含了一系列预设的主题…

作者头像 李华
网站建设 2026/4/30 10:39:24

企业级存储方案:LVM在生产环境的20个实战技巧

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个LVM实战模拟环境,包含以下场景:1) 在线扩展根分区 2) 损坏的PV数据恢复 3) 多磁盘条带化配置 4) 快照备份与回滚。要求每个场景提供分步操作指导和风…

作者头像 李华
网站建设 2026/5/1 7:18:48

PyFluent 终极指南:用 Python 轻松驾驭 Ansys Fluent 流体仿真

PyFluent 终极指南:用 Python 轻松驾驭 Ansys Fluent 流体仿真 【免费下载链接】pyfluent Pythonic interface to Ansys Fluent 项目地址: https://gitcode.com/gh_mirrors/py/pyfluent 想要用 Python 代码自动化你的 CFD 仿真工作吗?PyFluent 正…

作者头像 李华
网站建设 2026/4/30 13:29:55

路径规划终极指南:栅格与拓扑地图的完整技术解析

路径规划终极指南:栅格与拓扑地图的完整技术解析 【免费下载链接】PathPlanning Common used path planning algorithms with animations. 项目地址: https://gitcode.com/gh_mirrors/pa/PathPlanning 在机器人导航、自动驾驶和智能仓储等前沿技术领域&#…

作者头像 李华