多种标签之间数据通信实现方式 一、前言浏览器的每个标签是独立存在的也无法直接共享数据但在少数场景下需求要求在不同的标签页之间进行数据传输和数据通信这就需要使用跨标签的数据通信来实现功能需求。常用的标签之间的实现方案BroadCast Channelwindow.open window.postMessageWebSocket路由 QueryLocalStorage window.onstorageCookie SetIntervalServer WorkerShared WorkerIndexedDB setInterval二、Example2.1 BroadcastChannelBroadcastChannel 接口代理了一个命名频道可以让指定 origin 下的任意 browsing context 来订阅它。它允许同源的不同浏览器窗口Tab 页frame 或者 iframe 下的不同文档之间相互通信。通过触发一个 message 事件消息可以广播到所有监听了该频道的 BroadcastChannel 对象。申请者获取数据constapplyChannelnewBroadcastChannel(openApi-BChannel-apply);// 申请者通道constproviderChannelnewBroadcastChannel(openApi-BChannel-provider);// 提供者通道constuniqueIconopenapi-dosc#Math.random();applyChannel.postMessage({uniqueIcon});// 关闭申请者通道setTimeout((){applyChannel.close();},0);providerChannel.onmessage(event){if(event.target.nameopenApi-BChannel-providerevent.data.uniqueIconuniqueIcon){debugger;// todoproviderChannel.close();}};提供者发送数据constapplyChannelnewBroadcastChannel(openApi-BChannel-apply);// 申请者通道constproviderChannelnewBroadcastChannel(openApi-BChannel-provider);// 提供者通道constprivateData{money:$9999,};applyChannel.onmessage(event){// 判断专属通道if((event.target.nameopenApi-BChannel-apply)){providerChannel.postMessage({privateData,uniqueIcon:event.data.uniqueIcon,});// 任务完成关闭通道setTimeout((){applyChannel.close();providerChannel.close();});}};为了之间的通信安全我们在这儿预置实例化了申请者和提供者两个通信通道申请方先走专属的申请者通道‘openApi-BChannel-apply’去向提供方申请需要经费并提供申请方标识uniqueIcon提供方确认是己方‘openApi-BChannel-apply’提供方准备好经费后走专属的提供则通道下发给申请者。申请者接收到包裹后检验是否是从专属的提供者通道过来的并确认是否是自己的再勉为其难地收入囊中。记得在组件中使用的时候要及时的关闭申请者通道如果其他申请者也不需要数据时提供者实例通道也要关闭。2.2 window.open()window.postMessage()window.open(): Window 接口的 open() 方法是用指定的名称将指定的资源加载到新的或已存在的浏览上下文标签、窗口或 iframe中。window.postMessage(): window.postMessage() 方法可以安全地实现跨源通信。通常对于两个不同页面的脚本只有当执行它们的页面位于具有相同的协议通常为 https端口号443 为 https 的默认值以及主机 (两个页面的模数 Document.domain 设置为相同的值) 时这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制只要正确的使用这种方法就很安全。提供者通过 window.open()去新建标签页等新建标签页加载完成后触发 onload 事件给新标签页发送信息constnewTabDebugwindow.open(#/debug,_blank);newTabDebug.onload(){newTabDebug.postMessage({currNode:$9999},*);};申请者监听 message 事件接受到信息window.addEventListener(message,function(event){console.log(event.dataevent.data.currNode);});2.3 WebSocketWebSocket 对象提供了用于创建和管理 WebSocket 连接以及可以通过该连接发送和接收数据的 API。1在 Server 启用 Service Workernpm install-Sws// 安装 ws// 获得WebSocketServer类型letWebSocketServerrequire(ws).Server;// 创建WebSocketServer对象实例监听指定端口letservernewWebSocketServer({port:8000});// 创建保存所有已连接到服务器的客户端对象的数组letclients[];// 为服务器添加 connection 事件监听当有客户端连接到服务端时立刻将客户端对象保存进数组中。server.on(connection,function(client){if(clients.indexOf(client)-1){clients.push(client);console.log(有clients.length个客户端在线);// 为每个 client 对象绑定 message 事件// 当某个客户端发来消息时自动触发client.on(message,function(msg){console.log(msg.data);// 遍历 clients 数组中每个其他客户端对象并发送消息给其他客户端for(letkeyofclients){if(key!client){key.send(msg.data);}}});}});// 启动服务器的命令 node server.js(2) 提供者建立链接 发送数据constwsnewWebSocket(ws://localhost:8000);//创建Wevsocket实例化ws.onerrorfunction(){console.log(失败了);//建立失败的函数};constdata{id:newDate().getTime(),user:fx,dateTime:newDate().getTime(),msg:,};// 当连接建立成功触发 open 事件ws.onopenfunction(evt){console.log(建立连接成功 ...);// 连接建立成功以后就可以使用这个连接对象通信了// send 方法发送数据// ws.send(JSON.stringify(data));};当建立链接后会触发 webSocket 的实例的 onpen 事件此时 server 会接受到链接申请(3)申请者通过 onmessage API 监听(新建标签)varwsnewWebSocket(ws://localhost:8000);//创建Wevsocket实例化ws.onmessage(e){console.log(e.data);debugger;}; 到这里提供者 - server - 申请者 之间的通信就建立起来了这时提供者发送数据ws.send(JSON.stringify({name:晓东,age:22,money:$99}));此时 Server 端收到的是 Buffer 类型的二进制格式数据流而申请者收到的是 Blob 的对象那是因为 WebSocket 是通过二进制流进行数据通信的这就需要在 Server 将 Buffer 转为其他数据类型比如String 或 Objectclient.on(message,function(msg,isBinary){msgisBinary?msg:msg.toString();console.log(msg);console.log(isBinary);// 遍历 clients 数组中每个其他客户端对象并发送消息给其他客户端for(letkeyofclients){if(key!client){key.send(msg);}}});再发送数据时ws.send(JSON.stringify({name:小明,age:22,money:$9999}));ws.send(hahhaha);2.4 路由 Query通过 window.open(url, target, windowFeatures)打开新标签在新标签初始化完成的函数里通过 location.href 拿到 UrlParams再将参数解析出来即可。解析 UrlParamsfunctionparseParam(url){constparamsStr/.\?(.)$/.exec(url)[1];// 将 后面的字符串取出来constparamsArrparamsStr.split();// 将字符串以分隔后存在数组letparamsObj{};// 将params存到对象中paramsArr.forEach((param){// 处理有value的参数if(//.test(param)){let[key,val]param.split();// 分割key和valuevaldecodeURIComponent(val);// 解码val/^\d$/.test(val)?parseFloat(val):val;if(paramsObj.hasOwnProperty(key)){// 如果对象有key则添加一个值paramsObj[key][].concat(paramsObj[key],val);}else{// 如果对象没有这个key创建key并设置值paramsObj[key]val;}}else{// 处理没有value的参数paramsObj[param]true;}});returnparamsObj;}// testvarurlhttps://easylearn.baidu.com/edu-page/tiangong/questiondetail?id1711614621853513447frsearch;parseParam(url);2.5 LocalStorage window.onstoragelocalStorage只读的 LocalStorage 属性允许你访问一个 Document 源origin的对象 Storage存储的数据将保存在浏览器会话中。localStorage 类似 sessionStorage但其区别在于存储在 localStorage 的数据可以长期保留而当页面会话结束——也就是说当页面被关闭时存储在 sessionStorage 的数据会被清除。** window.onstorage** 当存储区域localStorage 或 sessionStorage被修改时将触发 storage 事件。提供者通过 localStorage.setItem()更新数据localStorage.setItem(we_are_famify,JSON.stringify({target:fater,data:{money:$9999}}));申请者通过 window.onstorage 监听事件来获取数据window.onstoragefunction(event){debugger;if(event.keywe_are_famify){console.log(event.newValue);}};2.6 Cookie SetInterval获取并设置与当前文档相关联的 cookie。可以把它当成一个 getter and setter。提供者将数据存入到 Cookie:document.cookiemoney$9999;申请者通过轮询来查阅 document.cookie 中是否有自己的字段。当查阅到自己所需的字段有值时清除掉自己的字段和定时器consttimersetInterval(function(){// 获取存储在 Cookie 中的消息constcookiesdocument.cookie.split(;);letmessage;for(leti0;icookies.length;i){constcookiecookies[i].trim();if(cookie.startsWith(money)){messagecookie.substring(money.length);break;}}// 处理消息if(message){console.log(Received money:,decodeURIComponent(message));// 清除 Cookie和定时器document.cookiemoney; expiresThu, 01 Jan 1999 00:00:00 UTC; path/;;clearInterval(timer);}},1000);2.7 Server WorkerService Worker API 的 ServiceWorker 接口提供了对 service worker 的引用。各个浏览上下文例如页面、worker 等可以与相同的 service worker 相关联每个浏览上下文都可以通过唯一的 ServiceWorker 对象访问。详细原理解析可以 readinghttps://juejin.cn/post/7283313180729573395?searchId20231204200524780957E4868B5A5CDB55。个人觉得很Nice~ 的一片好文。跟 webSocket 类似也需要另外侦听注册实例添加事件但不用另外起借助 node 或者其他工具 run 后台服务sw.js在这儿我将 ws.js 视为一个通信的工具所以我将该文件存放在静态资源public 目录下。self.addEventListener(message,async(event){constclientsawaitthis.clients.matchAll();clients.forEach(function(client){client.postMessage(event.data);});});self.addEventListener(activate,(event){clients.claim();console.log(Ready!);});其中的 activate 事件是为了 controller 不为 null。提供者 需要通过 sw.js 来注册使用 ServiceWorker.Container.register() 方法首次注册 service worker。如果注册成功service worker 就会被下载到客户端并尝试安装或激活这将作用于整个域内用户可访问的 URL或者其特定子集。最好在入口页 index.html 来进行注册也可以在提供者页初始化时进行注册【发送信息之前注册都可以一次就好~】就可以用 navigator.serviceWorker.controller.postMessage()去发送信息了。!--注册--navigator.serviceWorker.register(/sw.js).then((){console.log(service worker 注册成功);});!--发送信息--constmsg{money:$999,yourAge:22,from:提供者,to:申请者,}navigator.serviceWorker.controller.postMessage(JSON.stringify(msg));console.log(我给你一个礼物)申请者 在 web 项目的任何地方使用 navigator.serviceWorker.onmessage 来获得消息如果是多个信息交叉通信也可以同构 Name 或者 origin 来识别是不是自己所需要的消息。navigator.serviceWorker.onmessagefunction({data}){console.log(JSON.parse(data));debugger;};2.8 Shared WorkerSharedWorker 接口代表一种特定类型的 worker可以从几个浏览上下文中访问例如几个窗口、iframe 或其他 worker。它们实现一个不同于普通 worker 的接口具有不同的全局作用域。跟 Sever Worker 相似但又有些不一样先上代码同样的第一步先注册sw.js// 监听来自主页面的消息self.onconnectfunction(event){constportevent.ports[0];// 监听来自主页面的消息port.onmessagefunction(event){console.log(Received message from main page:,event.data);// 向主页面发送消息port.postMessage(event.data);};};// 在主页注册并挂在到window对象constworkernewSharedWorker(/sw.js);window.workerworker;申请者window.worker.port.onmessagefunction(event){console.log(申请者收到你的礼物,JSON.parse(event.data));};提供者constmsg{money:$999,yourAge:22,from:提供者,to:申请者};window.worker.port.postMessage(JSON.stringify(msg));2.9 IndexedDB setIntervalindexedDB 是 WindowOrWorkerGlobalScope 的一个只读属性它集成了为应用程序提供异步访问索引数据库的功能的机制。特点键值对储存 IndexedDB 内部采用对象仓库object store存放数据。所有类型的数据都可以直接存入包括 JavaScript 对象。对象仓库中数据以键值对的形式保存每一个数据记录都有对应的主键主键是独一无二的不能有重复否则会抛出一个错误。异步 IndexedDB 操作时不会锁死浏览器用户依然可以进行其他操作这与 LocalStorage 形成对比后者的操作是同步的。异步设计是为了防止大量数据的读写拖慢网页的表现。支持事务 IndexedDB 支持事务transaction这意味着一系列操作步骤之中只要有一步失败整个事务就都取消数据库回滚到事务发生之前的状态不存在只改写一部分数据的情况。同源限制 IndexedDB 受到同源限制每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库而不能访问跨域的数据库。支持二进制储存 IndexedDB 不仅可以储存字符串还可以储存二进制数据ArrayBuffer 对象和 Blob 对象。储存空间大 IndexedDB 的储存空间比 LocalStorage 大得多一般来说不少于 250MB甚至没有上限。储 存 在 电 脑 上 中 的 位 置 为 C:\Users\当 前 的 登 录 用 户\AppData\Local\Google\Chrome\User Data\Default\IndexedDB应用indexedDB进行标签之间的通信原理相似于LocalStorage setInterval将数据存储再轮询indexedDB获取到数据。但浏览器对其的兼容不太友好egIE也由于其存储量大的原因也称其数据库并且是存储在系统盘一旦数据存储的数据量大时用户在浏览器使用就会觉得莫名其妙的把盘给占满流氓行为而且前端一般也不会存储大量的数据但既然indexedDB面世也是有它的用武之地的。比如在网站文章的富文本编辑器要求有返回上一步功能草稿功能股票金融类的统计图数据数据是实时更新的可以把已经加载过的数据缓存到本地再次查询指定时间段的时候就减少后台压力了当然这些场景使用本地缓存不一定是最佳方案但是有indexedDB确实是可以优化业务的。相对于localstorage而言这绝对是前端存储的扛把子的存在也正是因为如此其学习成本和使用成本要相对而言较高不亚于学习数据库的操作指令有兴趣的伙伴可以去尝试一下Node express MongoDB搭建简易的后台系统尝尝鲜也存在读写事务互相阻塞批量操作数据读写时相较于慢。既然已经吹到前端的存储了那就顺便整理一下前端常用的存储特点三、总结BroadCast Channel优点第一次打开之后再传参无需刷新界面重新加载资源;可以同时使用多个频道或共用一个频道通信简单缺点受同源策略限制只会向同频道的同源页面发送或接受但也是其优势.LocalStorage window.onstorage优点第一次打开之后再传参无需刷新新界面重新加载资源;浏览器兼容性好操作简单便捷;缺点受同源策略限制LocalStroage 需在同源策略的前提下页面才能共享需要通过 LocalStroage 检控通信控制相对麻烦复杂场景使用不便捷;无痕环境下或部分浏览器隐身无法使用设置 localStorageeg:Safari就如 H5 无法设置 cookie从而无法触发到 onstrage。window.open window.postMessageService WorkerShared Worker优点理论上可以实现任何数据共享性能较好;缺点跨域不共享调试不方便兼容性不好。cookie SetInterval优点兼容性好易于上手和理解;缺点有存储大小限制轮询消耗性能发请求会携带 cookie。Websocket优点使用灵巧便捷且功能强大属于服务端给予的一个外挂缺点需要借助服务端的支持如果通信数据量大时比较消耗服务端资源但又有什么两者兼得的办法嘞必须在服务端添加监听。IndexedDB SetInterval结言之所以会有这么多实现方式即是技术更迭发展的足迹也是程序猿鬼才般地实现手段能够借助外挂法缓存等非专用通信方式来与其他的手段结合实现同等通信效果不禁感叹程序猿的奇思妙想代码世界的多姿多彩这些通信方式各有优劣选择适合的方式取决于具体的需求和场景选择合适的通信方式来实现跨标签页的通信。

相关新闻

最新新闻

电源线盘绕的电感效应:原理、风险与工程实践指南

电源线盘绕的电感效应:原理、风险与工程实践指南

这次我们来看一个在UPS电源、数据中心、工业设备布线中经常遇到的实际问题:将输入输出电源线盘绕成螺旋状(或称线圈状)后,通电时是否会产生电感效应,以及这种效应是否会对连接的设备产生影响。这并非一个抽象的学术问题…

2026/8/11 10:45:15
【爱马仕】Hermes 智能助手本地部署教程,整合包快速完成环境初始化

【爱马仕】Hermes 智能助手本地部署教程,整合包快速完成环境初始化

Windows 本地部署 Hermes 繁琐?整合部署包快速搭建本地智能体 不少用户想要体验 Hermes Agent 智能工具,但手动部署很容易卡在环境配置环节。 自行搭建需要安装各类依赖、调试运行环境,经常出现命令行报错、文件缺失等问题,对普通…

2026/8/11 10:45:15
抖音评论数据采集终极指南:三步批量导出到Excel的完整教程

抖音评论数据采集终极指南:三步批量导出到Excel的完整教程

抖音评论数据采集终极指南:三步批量导出到Excel的完整教程 【免费下载链接】TikTokCommentScraper 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokCommentScraper 想要深度分析抖音热门视频的用户评论,却苦于无法批量获取结构化数据&#…

2026/8/11 10:45:15
终极指南:如何用trackerslist让BT下载速度翻倍?[特殊字符]

终极指南:如何用trackerslist让BT下载速度翻倍?[特殊字符]

终极指南:如何用trackerslist让BT下载速度翻倍?🚀 【免费下载链接】trackerslist Updated list of public BitTorrent trackers 项目地址: https://gitcode.com/GitHub_Trending/tr/trackerslist 你是否曾经遇到过这样的困扰&#xff…

2026/8/11 10:45:15
SAP Fiori Launchpad混合架构内容集成技术解析

SAP Fiori Launchpad混合架构内容集成技术解析

1. 混合架构下的SAP Fiori Launchpad服务现状 在当今企业IT环境中,混合架构已成为主流选择。根据我过去五年参与过的12个SAP实施项目经验,超过80%的企业都采用了混合部署模式——部分系统在公有云,部分保留在本地数据中心。这种架构虽然灵活&…

2026/8/11 10:45:15
亚马逊店铺运营是什么?完整定义与核心价值解读

亚马逊店铺运营是什么?完整定义与核心价值解读

我见过一个做了三年淘宝的朋友,转来做亚马逊的第一天,打开卖家后台之后沉默了整整十分钟。后来他跟我说了一句话:"我以为换个平台只是换了个界面,没想到换的是整套逻辑。"这也是很多新手卖家共同的困惑——注册了账号、…

2026/8/11 10:40:15