纯前端怎么实现不同标签页下的数据通信

news2024/11/19 4:37:02

前言

我记得之前有做过这样的一个需求——可以简化的看作为一个 TODO List ,我打开了两个 tab 页,都是对应这个 TODO List

然后我在 A 页面新增一个,不出意外的话,在 B 页面是看不到的。产品当时跟我提了一下这个,让测试给我提了个 Bug

我那个时候下意识的反应就是找后端接一下 WebSocket ,但接一个 WebSocket 谈何简单,单单是公司网关那里分分钟让你搞一天都搞不定。

我就接着搜了一下,看看有没有纯前端的实现方案,还真让我找到了。今天我们就一起讨论下:纯前端如何实现不同标签页下的数据通信。

TODO List Demo

这里我为了演示,做了一个最简版本的 TODO List ,大家知道意思就行:

import { Button, Input, Row } from "antd";
import { useState } from "react";

const Todo = () => {
  const [list, setList] = useState([]);
  const [value, setValue] = useState("");
  const handleCreate = () => {
    if (!value) {
      return;
    }
    const arr = [...list];
    arr.push(value);
    setList(arr);
    setValue("");
  };
  return (
    <div style={{ margin: 20 }}>
      <Row>
        <Input
          value={value}
          onInput={(e) => setValue(e.target.value)}
          style={{ width: 200, marginRight: 16 }}
          placeholder="输入点什么"
        />
        <Button onClick={handleCreate} type="primary">
          增加
        </Button>
      </Row>
      <ul>
        {list.map((item) => {
          return <li>{item}</li>;
        })}
      </ul>
    </div>
  );
};

export default Todo;

image.png

代码很简单,仅为了后续演示数据同步使用。就是用一个输入框加一个确认按钮,然后把输入的东西 push 到数组里面,把这个数组渲染出来。

localStorage

localStorage 相信各位前端同学都不会陌生,数据存储在 localStorage 中是持久的,即使用户关闭了浏览器窗口,数据也会保留下来,直到用户手动清除或者被JS脚本清除。

在同源的情况下,localStorage存储的数据是共享的,也就是说假设我打开了两个同源的标签页 AB ,我在 A 中写入了 localStorage ,在 B 标签页是可以获取到的。

且我们是可以监听 localStorage 的变化的,既然数据能共享,取到的是同一份。而且还能监听数据的变化,这不就可以实现数据通信同步了吗?

首先,在 list 变化的时候写入 localStorage

useEffect(() => {
    window.localStorage.setItem(CACHE_KEY, JSON.stringify(list));
}, [list]);

然后在 localStorage 变更的时候更新 state 。注意:localStorage 的变化事件 (storage 事件) 在其他标签页或窗口修改 localStorage 时才会触发。

  const handleStorageChange = useCallback(
    (event) => {
      const { key, newValue } = event;
      if (isEmpty(newValue)) {
        setList([]);
      }
      if (key === CACHE_KEY) {
        if (isEmpty(newValue)) {
          setList([]);
        } else if (JSON.stringify(list) !== newValue) {
          setList(JSON.parse(newValue));
        }
      }
    },
    [list]
  );

  useEffect(() => {
    window.addEventListener("storage", handleStorageChange);
    return () => {
      window.removeEventListener("storage", handleStorageChange);
    };
  }, [handleStorageChange]);

所以为了验证这个功能,我们可以打开两个标签页来看看效果:

Kapture 2024-05-04 at 21.52.47.gif

可以看到,在 A 标签页输入的东西可以顺利同步到 B 标签页中,也是实现了纯前端下的数据通信。

但可能有人觉得,本身我这个功能不需要依赖 localStorage ,搞得我现在又需要在本地存储再存一份。有没有不依赖本地存储的跨标签页数据通信方式呢?

Broadcast Channel API

答案是有的,那就是——Broadcast Channel API,我们可以一起来看看 MDN 对它的解释:

Broadcast Channel API 可以实现同 源 下浏览器不同窗口,Tab 页,frame 或者 iframe 下的 浏览器上下文 (通常是同一个网站下不同的页面) 之间的简单通讯。

也就是说这个 API 设计出来就是为了让我们对同源的不同窗口做数据通信的。

看一下兼容性:

image.png

除了 IE 不支持,其他大多数主流浏览器都支持。

整体的 API 用起来十分简单,我们一起来看看。

首先刚开始需要加入或者创建一个频道,跟我们使用 ws 的时候一样,需要创建或者加入一个房间,组件销毁时退出频道。

  useEffect(() => {
    const bc = new BroadcastChannel(CHANNEL_NAME);
    channel.current = bc;
    channel.current.onmessage = function (ev) {
      if (ev?.data?.type === "add") {
        const arr = [...list];
        arr.push(ev.data.value);
        setList(arr);
      }
    };
    return () => {
      channel.current && channel.current.close();
    };
  }, [list]);

onmessage 中就可以接收到频道中其他标签页发送过来的消息,在这里获取到消息之后更新 state 。同样的,在新增数据的时候,通过频道发送消息。

  const handleCreate = () => {
    if (!value) {
      return;
    }
    const arr = [...list];
    arr.push(value);
    setList(arr);
    setValue("");
    channel.current.postMessage({
      type: "add",
      value,
    });
  };

一样也是可以实现跨标签页的数据通信的。

Kapture 2024-05-04 at 21.52.47.gif

最后

以上就是本文的全部内容,主要介绍了两种纯前端实现不同标签页下的数据通信的方式,如果你觉得有意思的话,点点关注点点赞吧~

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

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

相关文章

K-独立钻石(dfs),G-邪恶铭刻(贪心)

这两题&#xff0c;都是应该赛场上A出来的。 K.独立钻石 当时一直关注点在 I. Path Planning&#xff0c;没关注榜单&#xff0c;K,也能写&#xff0c;也就是dfs,从数据范围可以看出&#xff0c;直接暴力搜索。 代码 #include<bits/stdc.h> #define int long long #d…

JavaScript的当前时间设置及Date的运算

作者:私语茶馆 1.场景描述 如下图,在HTML刚加载时,需要将开始时间设置为默认当前时间,结束时间设置为当前时间后7天的时间。手工填写时间时,时间段不超过30天。 这里涉及到两个技术点: 1)Input Date的当前时间设置 2)date的运算 由于是动态修改HTML,所以采用…

【软件设计师】算法

1、算法的效率 时间复杂度:程序从开始到结束所需要的时间 空间复杂度&#xff1a;算法在运行过程中临时占用存储空间大小的度量 时间渐近复杂度&#xff1a;时间复杂度由最高次幂决定(判断大小技巧&#xff1a;将n10代入&#xff09; O(log2 n):二分查找法 O(n&#xff09;:for…

Echarts x轴坐标二级分组

在使用echarts 封装组件的时候&#xff0c;偶尔会遇到需要x轴坐标进行二层分组的需求。那么如何对echarts 进行二层分组呢&#xff0c;有以下几个步骤&#xff1a; 仅介绍二层分组的逻辑。有兴趣的可以进行三层延伸。 1&#xff0c;修改echarts Options 中xAxis 的配置。 此…

OpenHarmony 实战开发PhotoView——支持图片缩放、平移、旋转的一个优雅的三方组件

简介 PhotoView是OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;系统的一款图片缩放及浏览的三方组件&#xff0c;用于声明式应用开发&#xff0c;支持图片缩放、平移、旋转等功能。 使用场景 PhotoView为广大OpenHarmony应用开发者在处理图片时&#xf…

prompt提示词:如何让AI帮你提一个好问题

我们看完一篇文章的时候&#xff0c;有时候发给AI后&#xff0c;不知道如何问AI&#xff0c;不知道问哪些问题&#xff0c;你使用这个提示词&#xff0c;就可以让AI帮你想一个好问题&#xff0c;然后你用AI想好的问题再去问AI 能提出一个好的问题是非常难的 提示词 结合文章…

出现 Transaction rolled back because it has been marked as rollback-only 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 用户反馈的Bug如下所示: Transaction rolled back because it has been marked as rollback-only截图如下: 浏览器终端同样显示: 2. 原理分析 错误表明,在事务的生命周期内,遇到了某个异常或条件,导致该事务被标记…

elemnt ui 时间选择器。 当前日期往前推6个月以前的的不可选择

<div class"hengxiang"><div class"lefttitle titlesBt" style"color:#15a66a;"><div>建单起始日期</div><el-date-picker class"elinputs" type"date" placeholder"请输入起始日" v-…

【基础篇-Day7:JAVA面向对象的初级使用】

目录 1、类和对象1.1 类的介绍1.2 类和对象的关系1.3 类的组成 2、对象内存图2.1 单个对象内存图2.2 两个对象内存图2.3 两个引用指向相同内存图 3、成员变量和局部变量3.1 成员变量和局部变量的区别 4、this关键字4.1 this可以解决的问题4.2 this介绍4.3 this内存图4.4 this总…

01 一文理解,Prometheus详细介绍

01 一文理解&#xff0c;Prometheus详细介绍 介绍 大家好&#xff0c;我是秋意零。 Prometheus 是一个开源的系统监控和报警工具包&#xff0c;最初由SoundCloud开发&#xff0c;并在2012年作为开源项目发布。Prometheus 目前由Cloud Native Computing Foundation&#xff08…

git 学习(一)

一、版本控制 &#xff08;一&#xff09;介绍 版本迭代 每一次更新代码 都会出现新的版本如果我们需要之前的版本的文件 我们就得需要版本控制的文件 每一次更新的结果我们都保存下来 多人开发必须要用版本控制器 否则代价会很大 &#xff08;二&#xff09;主流的版本控制…

中科驭数驭云、超低时延网络案例双双入选第七届数字中国建设峰会数字化转型典型应用案例

5月24日-25日&#xff0c;第七届数字中国建设峰会在福州召开。在“数字赋能民营经济专业工作会议”上&#xff0c;中关村云计算产业联盟发布了《2024中小企业数字化转型典型应用案例集》&#xff0c;中科驭数驭云、超低时延网络两大方案入选。 作为国内领先的DPU芯片及解决方案…

初识C语言——第二十六天

函数的递归1 什么是递归呢&#xff1f; 递归的两个必要条件 void print(unsigned int n) {if (n > 9){print(n / 10);}printf("%d ", n % 10); }int main() {unsigned int num 0;scanf("%u", &num);//123//递归-函数自己调用自己print(num);//pr…

Ubuntu20.04安装ffmpeg,并捕获视频流

工控机&#xff1a;幻影峡谷 系统&#xff1a;Ubuntu20.04 摄像头&#xff1a;杰瑞微通环星光USB摄像头记录一下使用ffmpeg拉取视频流的原因&#xff1a;刚开始用的是ubuntu系统自带的 茄子 软件&#xff0c;但是视频流很卡&#xff08;非常卡&#xff0c;基本上不能用&#xf…

nuxt3+Element Plus项目搭建过程记录

背景 本文只记录项目搭建过程中遇到的一些问题和关键点&#xff0c;nuxt框架的说明和API请参照官网学习 官网&#xff1a;https://nuxt.com/docs/getting-started/introduction 1. 初始化项目 指令如下: npx nuxilatest init <project-name>我在安装过程中出现报错&a…

前端项目上线

目录 1项目打包 2本地服务器部署 2.1具体操作步骤 2.2解决刷新 404 问题 2.3请求无法发送问题 3nginx 服务器部署 3.2nginx 配置代理练习 安装nginx nginx部署启动项目 3.3nginx 部署前端项目 4云服务器部署 本地资源上传 配置服务器与nginx 1项目打包 ●我…

lvm概述和配额

lvm概述和配额 文章目录 lvm概述和配额LVM概述1、逻辑卷的作用&#xff1a;2、lvm主要命令和实操磁盘配额创建data目录&#xff0c;进入data目录限制创建文件数 LVM概述 逻辑卷管理liunx系统下对硬盘分区的一种管理机制 lvm机制特别适合管理大储存设备&#xff0c;可以动态的…

回答篇二:测试开发高频面试题目

引用之前文章&#xff1a;测试开发高频面试题目 本篇文章是回答篇&#xff08;持续更新中&#xff09; 1. 在测试开发中使用哪些自动化测试工具和框架&#xff1f;介绍一下你对其中一个工具或框架的经验。 a. 测试中经常是用的自动化测试工具和框架有Selenium、Pytest、Postman…

【Linux】解决误操作libc.so.6导致的问题,补充:升级glibc注意事项

千万不要轻易动/usr/lib64/libc.so.6。 glibc是Linux系统中最底层的api&#xff0c;Linux几乎所有运行库都依赖glibc。/usr/lib64/libc.so.6属于glibc&#xff0c;在centos7中是个软链接。 一旦误删或误操作libc.so.6&#xff0c;或者glibc新版本不兼容等原因&#xff0c;都可…

推荐一个 Java 开源企业级新能源汽车智能共享充电桩管理平台

文末可获取 Orise 平台源码 01 Orise 智能充电桩管理平台 奥升( Orise ) 新能源汽车充电桩管理 Saas 云平台是一个集充电设备管理、用户充电管理、线上小程序内容管理于一体的综合管理平台。Orise充电桩平台支持高并发业务、业务动态伸缩、桩通信负载均衡&#xff0c;通过Docke…