当前位置: 首页 > news >正文

前端跨页面通信方案介绍

在浏览器中,我们可以同时打开多个Tab页,每个Tab页可以粗略理解为一个“独立”的运行环境,即使是全局对象也不会在多个Tab间共享。然而有些时候,我们希望能在这些“独立”的Tab页面之间同步页面的数据、信息或状态。这就是本文说说的跨页面通信方案,那么目前有哪些跨页面的通信方案呢?本文重点介绍一下。

同源页面之间跨页面通信一般有如下几种方案。

一、BroadCast Channel

目前查了一下兼容性,除了ie之外,所有浏览器基本都支持这个api了,所以可以大胆用起来,假如确实要支持ie,也可以用polyfill。

具体语法和websocket有点像如下:

  const bc = new BroadcastChannel('haorooms');//可以接受一个DOMString作为 name,用以标识这个 channel。在其他页面,可以通过传入相同的 name 来使用同一个广播频道。只用同样标识的页面才能收到广播,不同的收不到。console.log(bc.name) // 输出构造实例的标识,haorooms。bc.onmessage = function(e) {// 通过onmessage监听事件console.log('receive:', e.data);};bc.addEventListener('message',(e)=>{// 通过addEventLister监听事件,和上面的onmessage都可以,二选一,我个人倾向addEventlisterconsole.log('receivebyaddEventlistener:', e.data);})bc.onmessageerror = function(e) {console.warn('error:', e);}bc.postMessage('hello haorooms test broadcastchannel')

关闭

bc.close();

备注:这种方式好处是发送广播之后,自己 不会再收到,其他使用了相同实例的页面可以时时收到。用起来也很方便,非常简单和易用。

二、Service Worker

PWA的Service Worker也可以实现 不同页面之间的通信。

步骤如下:

首先,需要在页面注册 Service Worker:

/* 页面逻辑 */
navigator.serviceWorker.register('../haorooms.sw.js').then(function () {console.log('Service Worker 注册成功');
});

其中../haorooms.sw.js是对应的 Service Worker 脚本。Service Worker 本身并不自动具备“广播通信”的功能,需要我们添加些代码,将其改造成消息中转站:

/* ../haorooms.sw.js Service Worker 逻辑 */
self.addEventListener('message', function (e) {console.log('service worker receive message', e.data);e.waitUntil(self.clients.matchAll().then(function (clients) {if (!clients || clients.length === 0) {return;}clients.forEach(function (client) {client.postMessage(e.data);});}));
});

处理完 Service Worker,我们需要在页面监听 Service Worker 发送来的消息。

/* 页面逻辑 */
navigator.serviceWorker.addEventListener('message', function (e) {const data = e.data;const text = '[receive] ' + data.msg + ' —— haorooms_tab' + data.from;console.log('[Service Worker] receive message:', text);
});

最后,当需要同步消息时,可以调用 Service Worker 的postMessage方法:

/* 页面逻辑 */
navigator.serviceWorker.controller.postMessage(mydata);

三、LocalStorage

作为前端,LocalStorage是再熟悉不过了,但是用这个作为页面通信,还是头一次。这里通信其实只是简单的通信,主要通过LocalStorage的事件来完成的。

当 LocalStorage 变化时,会触发storage事件。利用这个特性,我们可以在发送消息时,把消息写入到某个 LocalStorage 中;然后在各个页面内,通过监听storage事件即可收到通知。

window.addEventListener('storage', function (e) {if (e.key === 'haorooms_localstoragekey') {const data = JSON.parse(e.newValue);const text = '[receive] ' + data.msg + ' —— haorooms_tab1 ' + data.from;console.log('[Storage I] receive message:', text);}
});

四、其他

之所以写其他,是因为方案只是可以完成页面通信,但是不是实际意义上面的通信,例如Shared Worker、IndexedDB、cookie,可以通过共享存储的方式来完成通信。window.open + window.opener这种方式可以通过扣扣相传的方式完成通信,还有websocket方式可以通过服务中转方案完成通信。 这里不详细展开介绍,感兴趣的可以搜索。

非同源页面之间的通信

非同源通信相对较麻烦一些,我们可以使用一个用户不可见的 iframe 作为“桥”。由于 iframe 与父页面间可以通过指定origin来忽略同源限制,因此可以在每个页面中嵌入一个 iframe (例如:haorooms.com/bridge.html),而这些 iframe 由于使用的是一个 url,因此属于同源页面,其通信方式可以复用上面第一部分提到的各种方式。

/* iframe 内代码 */
const bc = new BroadcastChannel('haorooms_bc');
// 收到来自页面的消息后,在 iframe 间进行广播
window.addEventListener('message', function (e) {bc.postMessage(e.data);
}); 其他 iframe 收到通知后,则会将该消息同步给所属的页面:
/* iframe 内代码 */
// 对于收到的(iframe)广播消息,通知给所属的业务页面
bc.onmessage = function (e) {window.parent.postMessage(e.data, '*');
};

相关文章:

  • JavaScript 删除数组中指定元素的6种方法
  • C语言第三十九弹---预处理(上)
  • 【QT5-程序控制电源-串口通讯-<低成本>-程控电源方案-上位机-基础样例【3】】
  • 面试题 之 vue
  • 数据库-root密码丢失的重置方案(win11环境)
  • andv vue 实现多张图片上传
  • 史上最强 PyTorch 2.2 GPU 版最新安装教程
  • golang和Java的简单介绍和对比
  • cesium 加载gltf并实时改变位置 CallbackProperty方式
  • Mybatis 之 useGeneratedKeys
  • nodejs的express负载均衡
  • 手写三维点云配准的迭代最近点(ICP)算法
  • 算法学习系列(四十五):DFS之剪枝与优化
  • 【c++20】CPP-20-STL-Cookbook 学习笔记
  • 【Qt】QtCreator交叉编译环境配置Qt mkspec
  • __proto__ 和 prototype的关系
  • co模块的前端实现
  • download使用浅析
  • Facebook AccountKit 接入的坑点
  • select2 取值 遍历 设置默认值
  • Solarized Scheme
  • webpack入门学习手记(二)
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 对超线程几个不同角度的解释
  • 构建工具 - 收藏集 - 掘金
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 漂亮刷新控件-iOS
  • 区块链分支循环
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 探索 JS 中的模块化
  • #大学#套接字
  • (function(){})()的分步解析
  • (十八)SpringBoot之发送QQ邮件
  • (转) Face-Resources
  • ***详解账号泄露:全球约1亿用户已泄露
  • ../depcomp: line 571: exec: g++: not found
  • .gitignore
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .skip() 和 .only() 的使用
  • ;号自动换行
  • @Transient注解
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [<MySQL优化总结>]
  • [C#]OpenCvSharp使用帧差法或者三帧差法检测移动物体
  • [C++打怪升级]--学习总目录
  • [C++数据结构](22)哈希表与unordered_set,unordered_map实现
  • [CISCN2019 华东北赛区]Web2
  • [elastic 8.x]java客户端连接elasticsearch与操作索引与文档
  • [HJ56 完全数计算]
  • [JS]数据类型
  • [js高手之路] dom常用API【appendChild,insertBefore,removeChild,replaceChild,cloneNode】详解与应用...