【前端技术】标签页通讯localStorage、BroadcastChannel、SharedWorker的技术详解

news2025/1/13 17:28:10

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

【前端技术】标签页通讯localStorage、BroadcastChannel、SharedWorker的技术详解

  • 前言
  • 标签页通信的应用场景
    • ❶ 用户登录状态同步
    • ❷ 实时数据更新
    • ❸ 多标签页协同工作
    • ❹ 购物车同步
    • ❺视频、音频播放同步
  • 第一种:localStorage
  • 第二种:BroadcastChannel API
  • 第三种:SharedWorker
  • 结语

前言

随着 Web 应用的复杂化和功能的增加,很多时候我们某些业务功能需要实现标签页间的通讯,基于这种需求下,我们必须要掌握一些标签页通讯的技术,本文博主将和大家分享三种常见的标签页通讯技术: localStorage 事件、 BroadcastChannel APISharedWorker

标签页通信的应用场景

浏览器标签页之间的通讯在实际应用中有很多场景。下面博主举几个常见的例子,展不同的需求和解决方案

❶ 用户登录状态同步

应用场景:用户在一个标签页中登录或注销,其他打开同一应用的标签页需要同步登录状态。

解决方案:使用 localStorage 事件或 BroadcastChannel


❷ 实时数据更新

应用场景:在一个标签页中更新数据,其他标签页需要实时显示更新结果,例如股票行情、实时聊天消息等。

解决方案:使用 BroadcastChannel 实现高效的实时通讯。


❸ 多标签页协同工作

应用场景:用户在多个标签页中打开同一个应用,需要各标签页协同工作。例如,在一个标签页中填写表单,另一个标签页显示表单预览

解决方案:使用 SharedWorker 进行复杂数据和状态共享,或者 BroadcastChannel 进行简单消息传递


❹ 购物车同步

应用场景:用户在一个标签页中添加商品到购物车,其他标签页需要同步购物车内容

解决方案:使用 localStorage 事件或 BroadcastChannel 实现购物车内容的同步


❺视频、音频播放同步

应用场景:用户在多个标签页中同时打开同一个视频,控制一个标签页的视频播放,其他标签页的视频需要同步播放或暂停(可以参考国内的酷狗音乐网站: 播放音乐标签页的效果

解决方案:使用 BroadcastChannel 实现同步控制


以上举例仅仅是标签页通讯应用场景的其中几种,实际上还存在更多场景,博主就不一一展开了

第一种:localStorage

在这里插入图片描述
localStorage 是一种持久化的存储机制,它允许在浏览器中存储键值对。当 localStorage 的数据在一个标签页中被修改时,其他所有打开同一页面的标签页都会接收到一个 storage 事件。这一特性使得我们可以利用 localStorage 实现不同标签页之间的通讯。

localStorage 的基本特点

  • 持久性:数据存储在 localStorage 中,即使浏览器关闭后也会保留
  • 同源策略:同一来源(origin)下的所有页面都可以访问相同的 localStorage 数据
  • 容量限制:大多数浏览器限制在 5MB 左右

代码示例
下面我们通过一个具体的示例,展示如何利用 localStorage 实现标签页之间的通讯

标签页 A:发送消息

<!DOCTYPE html>
<html>
<head>
    <title>标签页 A</title>
</head>
<body>
    <button onclick="sendMessage('这是来自标签页A的消息')">发送消息</button>

    <script>
        function sendMessage(message) {
            localStorage.setItem('message', message);
        }
    </script>
</body>
</html>

标签页 B:接收消息

<!DOCTYPE html>
<html>
<head>
    <title>标签页 B</title>
</head>
<body>
    <script>
        window.addEventListener('storage', (event) => {
            if (event.key === 'message') {
                console.log('我是标签页B接受到的消息: ', event.newValue);
            }
        });
    </script>
</body>
</html>

localStorage标签页通讯优点

  • 简单易用:实现方法简单,代码量少
  • 浏览器支持广泛:大多数现代浏览器都支持 localStorage

localStorage标签页通讯缺点

  • 同步问题:storage 事件是异步的,不适用于需要实时通讯的场景。
  • 数据存储限制:localStorage 容量有限,一般为 5MB。
  • 安全性:localStorage 中的数据是明文存储的,需要注意敏感数据的存储安全。

第二种:BroadcastChannel API

在这里插入图片描述

BroadcastChannel 是一种用于在同一来源(同一协议、主机名和端口号)下不同浏览器上下文(如标签页iframeWorkerService Worker)之间进行消息广播的 API。它提供了一种简便、可靠的方法来实现跨上下文的实时通讯

BroadcastChannel 的基本概念

  • 广播频道:BroadcastChannel 创建的实例代表一个特定的广播频道,所有监听该频道的上下文都能接收该频道发送的消息
  • 消息广播:通过 postMessage 方法发送消息,所有监听该频道的上下文都会收到消息
  • 消息监听:通过 onmessage 事件处理器接收和处理来自该频道的消息

BroadcastChannel 的特点

  • 实时通讯:能够在不同浏览器上下文之间进行实时消息传递。
  • 简洁易用:API 简单明了,只需少量代码即可实现。
  • 同源策略:确保安全性,只有同源的上下文才能相互通讯。

基本用法

创建频道:在多个上下文中使用相同的频道名称创建 BroadcastChannel 实例

const channel = new BroadcastChannel('my_channel');

发送消息:在任意一个上下文中,通过 postMessage 方法向频道发送消息

channel.postMessage('Hello from one context');

接收消息:在其他上下文中,通过监听 onmessage 事件接收消息

channel.onmessage = (event) => {
    console.log('Received message:', event.data);
};

代码示例
通过上述基本用法的介绍,我们现在可以用一个代码示例来演示一下

标签页 A 的代码

<!DOCTYPE html>
<html>
<head>
    <title>Page A</title>
</head>
<body>
    <button onclick="sendMessage()">发送消息</button>
    <script>
        const channel = new BroadcastChannel('my_channel');
        
        function sendMessage() {
            channel.postMessage('这是来自标签页A的消息');
            //传递对象
            channel.postMessage({ type: 'update', data: '更新的数据' });
        }
    </script>
</body>
</html>

标签页 B 的代码

<!DOCTYPE html>
<html>
<head>
    <title>Page B</title>
</head>
<body>
    <script>
        const channel = new BroadcastChannel('my_channel');

        channel.onmessage = (event) => {
            console.log('标签页B接受消息:', event.data);
            //接受对象
            if (event.data.type === 'update') {
        		console.log('标签页B接受update类型消息:', event.data.data);
    		}
        };
    </script>
</body>
</html>

BroadcastChannel通讯优点

  • 实时性好:消息几乎是实时传递的,适用于需要即时通讯的场景
  • 使用简单:不需要复杂的设置,易于实现和维护
  • 跨上下文:支持标签页iframeWorker 和 Service Worker 之间的通讯,适用范围广

BroadcastChannel通讯缺点

  • 不持久化:消息不会持久化,页面刷新或关闭后,之前的消息无法再获取
  • 同源限制:只能在同源上下文之间通讯,不同来源无法相互通讯

第三种:SharedWorker

在这里插入图片描述
SharedWorker 是一种允许多个浏览器上下文(如标签页iframe)共享一个 Worker 实例的技术,能够实现跨多个上下文的通讯和数据共享。通过 SharedWorker 我们可以在同一来源(同一协议、主机名和端口号)下的不同浏览器上下文之间进行高效的通讯

SharedWorker 的基本概念

  • SharedWorker 实例:多个上下文共享一个 Worker 实例,所有上下文可以通过这个 Worker 实例进行通讯
  • 连接和通讯:每个上下文通过 port 对象与 SharedWorker 通讯,portMessagePort 的实例
  • 消息传递:通过 postMessage 方法发送消息,通过 onmessage 事件处理器接收消息

SharedWorker 的特点

  • 共享实例:多个上下文共享一个 Worker 实例,节省资源
  • 双向通讯:通过 MessagePort 实现双向通讯
  • 同源策略:确保安全性,只有同源的上下文才能相互通讯

基本用法

创建和连接 SharedWorker:在 JavaScript 文件中定义 SharedWorker 脚本

// sharedWorker.js
self.onconnect = function(event) {
    const port = event.ports[0];
    port.onmessage = function(event) {
        // 处理来自页面的消息
        console.log('接收来自页面的消息:', event.data);
        
        // 可以将消息发送给其他连接的端口
        port.postMessage('来自SharedWorker的回复');
    };
};

在 HTML 页面中创建并连接 SharedWorker

// 页面 A 和页面 B 中的代码
const sharedWorker = new SharedWorker('sharedWorker.js');
const port = sharedWorker.port;

// 发送消息
port.postMessage('Hello from Page');

// 接收消息
port.onmessage = (event) => {
    console.log('Received from SharedWorker:', event.data);
};

示例代码
编写一个 SharedWorker 脚本 sharedWorker.js

let connections = [];

self.onconnect = function(event) {
    const port = event.ports[0];
    connections.push(port);

    port.onmessage = function(event) {
        console.log('Received from page:', event.data);
        
        // 广播消息给所有连接的端口
        connections.forEach(conn => {
            if (conn !== port) {
                conn.postMessage(event.data);
            }
        });
    };
    port.start();
};

标签页 A 的代码

<!DOCTYPE html>
<html>
<head>
    <title>页面 A</title>
</head>
<body>
    <button onclick="sendMessage()">发送页面A消息</button>

    <script>
        const sharedWorker = new SharedWorker('sharedWorker.js');
        const port = sharedWorker.port;
        port.start();

        function sendMessage() {
            port.postMessage('这是来自页面A的消息');
        }

        port.onmessage = (event) => {
            console.log('接收来自SharedWorker的消息:', event.data);
        };
    </script>
</body>
</html>

标签页 B 的代码

<!DOCTYPE html>
<html>
<head>
    <title>Page B</title>
</head>
<body>
	<button onclick="sendMessage()">发送页面B消息</button>
    <script>
        const sharedWorker = new SharedWorker('sharedWorker.js');
        const port = sharedWorker.port;
        port.start();

		function sendMessage() {
            port.postMessage('这是来自页面B的消息');
        }

        port.onmessage = (event) => {
            console.log('接收来自SharedWorker的消息:', event.data);
        };
    </script>
</body>
</html>

SharedWorker优点

  • 高效资源利用:共享一个 Worker 实例,减少内存和 CPU 占用
  • 灵活的消息处理:可以在 Worker 中集中处理和分发消息,适用于复杂的通讯需求
  • 持久连接:连接建立后可以长时间保持,不需要频繁建立和销毁连接

SharedWorker缺点

  • 实现复杂:相比 BroadcastChannel,实现起来稍微复杂一些
  • 同源限制:只能在同源上下文之间通讯,不同来源无法相互通讯
  • 浏览器支持:部分旧版浏览器可能不支持 SharedWorker

结语

到这里博主已经详细介绍了三种常见的浏览器标签页通讯方式,包括 localStorage 事件、BroadcastChannel APISharedWorker,这些技术各有优劣,小伙伴可以根据实际需求选择合适的解决方案,以实现高效的标签页间通讯。

文中的代码样例大家可以直接复制测试运行效果,如果本文对您有所帮助,希望 一键三连 给博主一点点鼓励,如果您有任何疑问或建议,请随时留言讨论!


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1848908.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apple - Text Attribute Programming Topics

本文翻译整理自&#xff1a;Text Attribute Programming Topics&#xff08;更新日期&#xff1a;2004-02-16 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextAttributes/TextAttributes.html#//apple_ref/doc/uid/10000088i 文章目录 一、文…

http发展史(http0.9、http1.0、http1.1、http/2、http/3)详解

文章目录 HTTP/0.9HTTP/1.0HTTP/1.1队头阻塞&#xff08;Head-of-Line Blocking&#xff09;1. TCP 层的队头阻塞2. HTTP/1.1 的队头阻塞 HTTP/2HTTP/3 HTTP/0.9 发布时间&#xff1a;1991年 特点&#xff1a; 只支持 GET 方法没有 HTTP 头部响应中只有 HTML 内容&#xff0…

C语言入门系列:可迁移的数据类型

文章目录 1&#xff0c;精确宽度类型(exact-width integer type)2&#xff0c;最小宽度类型&#xff08;minimum width type&#xff09;3&#xff0c;最快的最小宽度类型&#xff08;fast minimum width type&#xff09;4&#xff0c;可以保存指针的整数类型。5&#xff0c; …

云原生微服务开发日趋成熟:有效拥抱左移以改善交付

在软件工程和应用程序开发方面&#xff0c;云原生已经成为许多团队的常用术语。当人们调查云原生的世界时&#xff0c;他们经常会得出这样的观点&#xff1a;云原生的整个过程都是针对大型企业应用程序的。几年前&#xff0c;情况可能确实如此&#xff0c;但随着 Kubernetes 等…

Redis-使用 jedis 操作数据

文章目录 1、Jedis简介2、环境准备3、创建maven普通项目,导入如下依赖4、测试JAVA程序和Redis之间的通信 1、Jedis简介 "Jedis" 通常是作为 "Java Redis" 的缩写或简称来理解的。Java Embedded Data Structures Interface 表示 Java嵌入式数据结构接口 2、…

45、基于深度学习的螃蟹性别分类(matlab)

1、基于深度学习的螃蟹性别分类原理及流程 基于深度学习的螃蟹性别分类原理是利用深度学习模型对螃蟹的图像进行训练和识别&#xff0c;从而实现对螃蟹性别的自动分类。整个流程可以分为数据准备、模型构建、模型训练和性别分类四个步骤。 数据准备&#xff1a; 首先需要收集包…

C# 中的隐式和显式类型转换

当你需要转换值的类型时&#xff0c;可以使用类型转换。只有当你要转换的两种类型兼容时&#xff0c;才有可能。 当你收到错误“无法隐式将一种类型转换为另一种类型”时&#xff0c;说明你转换的两种类型不兼容。 int integer; // 声明一个名为 integer 的整型变量 integer …

【Gradio】如何设置 Gradio 数据框的样式

简介 数据可视化是数据分析和机器学习的关键方面。Gradio DataFrame 组件是一种流行的方式&#xff0c;在网络应用程序中显示表格数据&#xff08;特别是以 pandas DataFrame 对象的形式&#xff09;。 本文将探讨 Gradio 的最新增强功能&#xff0c;这些功能允许用户整合 pand…

解决vmware “处理器不支持 XSAVE。无法打开此虚拟机的电源。“

1,打开windows 10-11 的 虚拟机平台 选择 “开始”&#xff0c;输入“Windows 功能”&#xff0c;然后从结果列表中选择“打开或关闭 Windows 功能 ”。 在刚刚打开的 “Windows 功能”窗口中&#xff0c;找到“虚拟机平台 ”并将其选中。 选择“确定”。 可能需要重启电脑。…

节能减排如何替电子行业巨头降低成本

尖端科技与环境之间的矛盾&#xff0c;已经不再是科幻小说家笔下的虚构。 先进芯片制造从熔化硅开始&#xff0c;到使用大功率激光进行光刻&#xff0c;再到创造和维护真空状态&#xff0c;以及持续清洁工作&#xff0c;每一个环节都需要大量的电力支持。据统计&#xff0c;半…

在Windows上用MinGW编译OpenCV项目运行全流程

一、准备软件 OpenCV源码CMake工具MinGW工具链&#xff08;需要选用 posix 线程版本&#xff1a;原因见此&#xff09; 二、操作步骤 官网提供了VC16构建版本的二进制包&#xff0c;但是没有给出GCC编译的版本。所以如果使用MinGW进行构建&#xff0c;那就只能从源码开始构建…

聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例

前言 dynamic 是一种有别于传统变量类型的动态类型声明&#xff0c;刚开始接触可能在理解上会有些困难&#xff0c;可以简单地把它理解为一个盲盒&#xff0c;你可以任意猜测盒子有什么东西&#xff0c;并认为这些东西真正存在而进行处理&#xff0c;等到真正打开时&#xff0…

【尚庭公寓SpringBoot + Vue 项目实战】预约看房与租约管理(完结)

【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】预约看房与租约管理&#xff08;完结&#xff09;1、业务说明2、接口开发2.1、预约看房管理2.1.1.保存或更新看房预约2.1.2. 查询个人预约…

mysql的安装以及分享navicat for MySQL

前言 根据网上分享的安装方法以及自己遇到的问题解决方法 一、mysql是什么&#xff1f; mysql 是一个开放源码的小型关联式数据库管理系统 二、安装过程 1.下载安装包 下载地址&#xff1a;MySQL :: Download MySQL Community Server 跳过直接下载&#xff0c;解压即可 …

10.华为路由器使用ospf动态路由连通两个部门网络

目的&#xff1a;实验ospf动态路由协议连通A与B部门 AR1配置 [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [Huawei]vlan batch 10 [Huawei]int Vlanif 10 [Huawei]int e0/0/0 [Huawei-Ethernet0/0/0]port link-type access [Huawei-Ethernet0/0/0]por…

Spring Bean 生命周期详解

Spring Bean 生命周期详解 在 Spring 框架中&#xff0c;Bean 的生命周期由 Spring 容器全权管理。了解和掌握 Bean 的生命周期对于使用 Spring 开发稳定且高效的应用程序至关重要。本文将详细介绍 Spring Bean 生命周期的五个主要阶段&#xff1a;实例化、属性注入、初始化、…

Avue-data数据大屏显示饼图(附Demo)

目录 前言1. Sql查询2. 颜色细节 前言 对于这部分知识&#xff0c;原先有过柱状图实战&#xff1a;Avue-data数据大屏显示柱状图&#xff08;附Demo讲解&#xff09; 以下直奔主题&#xff0c;以Sql数据库数据为主 1. Sql查询 以饼图为例&#xff0c;需要返回的形式如下&am…

在敏捷项目管理中实施 Scrum 方法

在本文中&#xff0c;我将阐明敏捷项目管理中的 Scrum 流程。我将深入探讨 Scrum 方法论中不可或缺的角色。本文将全面概述敏捷开发中的 Scrum 流程。我将解释 Scrum 的核心组件&#xff0c;详细探索端到端 Scrum 流程。在本文结束时&#xff0c;您将清楚地了解 Scrum 的工作原…

Ant Design Vue Cascader 级联选择 错位问题

当Cascader 多个的时候 对应的下列会错位 如果滚动 他不会跟着元素 而是会跟着屏幕滚动&#xff0c;如下效果 解决方法 在Cascader 标题添加 getPopupContainer 属性监听对应的位置&#xff0c;返回对应的元素 <a-cascader class"smart-width-100 " v-model:…

QThread 与QObject::moveToThread在UI中的应用

1. QThread的两种用法 第一种用法就是继承QThread&#xff0c;然后覆写 virtual void run()&#xff0c; 这种用法的缺点是不能利用信号槽机制。 第二种用法就是创建一个线程&#xff0c;创建一个对象&#xff0c;再将对象moveToThread, 这种可以充分利用信号槽机制&#xff…