一个简单的watch以及ESModule导入和解构的区别

news2024/12/23 13:43:51

背景

最近写了个很有意思的方法,感觉还蛮不错的就分享一下。起先是我在写calss组件的时候遇到一个问题,我需要监听一个导入的值,导入的值最开始是undefined,经过异步操作以后会得到一个新的值,而我需要在这个class组件中拿到这个新的值去做操作。如果是在函数式组件中我们可以使用useEffect去监听这个值的变化,虽然useEffect监听的是stateprops,但是经过我的实践发现在本案例中还是可以监听到的,先话不多说开始详细展开说说吧。

发现问题

假设我们有个class组件A,然后我们在组件A中导入一个文件:

import { ets } from "../sse";

sse.js文件中我们有创建、关闭eventsource的方法以及它的实例,然后我们将他们导出这里就简单介绍下不展示代码了,这里的ets就代表eventsource的实例。

因为业务需要,我们并不是在这个组件A中去创建的eventsource连接而是在另外一个组件经过请求后创建的,那么我们什么时候在组件A去获取实例就成了一个很大的问题,因为我不知道实例是什么时候被初始化的。

其实解决问题的方法有很多,例如组件的通讯、创建缓存并监听缓存的变化等等都是可以的,但是或多或少会有一些麻烦和其他问题。这里不管是函数式组件还是Vue都可以通过监听去很方便的完成,但是class组件就很难去完成了,因为class组件只能去监听state和prop的变化,那我们能不能简单实现一个简单的watch去完成一个简单的监听呢?接下来就听我娓娓道来。

解决

创建方法

我们参考Vue的watch方法,这个方法需要一个依赖和一个依赖更新以后触发的回调函数,并且Vue是通过Proxy代理去监听的,既然有了大致的思路我们就可以开始去完成方法了。

首先我们在sse.js文件中创建一个watchEventSourceCreate方法,因为本案例中的依赖就是EventSource实例,所以我们可以不用封装依赖变量。我们主要的思路就是创建一个proxy,然后再利用set方法去调用我们传递的回调实现watch方法,具体方法如下:

let proxy;
const watchEventSourceCreate = (func, context) => {
  if (ets) {
    func(ets);
  } else {
    proxy = new Proxy(
      {},
      {
        get(target, key) {
          return target[key];
        },
        set(target, key, value) {
          if (key === "ets") {
            func.bind(context)(value);
          }
          target[key] = value;
          return true;
        },
      }
    );
  }
};

首先我创建了一个proxy变量,然后在我们创建的watchEventSourceCreate方法中创建代理,为什么我们不在申明proxy变量的时候去创建这个代理呢,原因很简单,我们需要在set方法中去调用我们的目标函数,但是在sse.js文件中我们只能在watchEventSourceCreate方法中拿到这个回调函数,所以我们声明这个代理必须要在watchEventSourceCreate中。

剩下的就比较好理解了,判断是否赋值ets,如果赋值了就调用回调函数,记得绑定this,虽然在本案例中不绑定也可以,但是这里还是为了保证稳定下绑定了this。

接下来的就是在创建eventsource的方法中去赋值。这一步很简单:

if (proxy) {
    proxy.ets= ets;
  }

使用

我们在组件A导入我们创建好的方法:

import { ets, watchEventSourceCreate } from "../sse";

因为这个watch需要传入一个触发后的处理函数,所以我们先定义一个处理函数,这个函数会被传入一个参数,这个参数在本案例中就是eventSource实例,其实要不要这个形参都不重要,因为我们主要是需要判断他的触发时机

handle(ets){
  //处理逻辑
  、、、
}

然后在componentDidMount钩子函数中去创建这个watch:

componentDidMount(){
  watchEventSourceCreate (this.handle, this)
}

需要注意的是在本案例中handle会在被创建后立即触发,因为我的业务需要是创建eventsource的监听,所以我只需要获取到实例就好,如果需要更深逻辑的判断我们可在set中将旧值和新值都传给目标函数,这样就可以在目标函数中去做比较,这样的话就更贴近Vue的Watch一点。

拓展

其实除了使用watch,我们还可以使用一个递归方法去判断ets的值。

import { ets } from "../sse";

componentDidMount(){
  this.handle()
}

handle(){
  if(ets){
    //逻辑...
  }else{
    this.handle()
  }
}

说说我为什么不这么写,首先就是这么写是很危险的,单纯的通过ets是否有值去判断是否进行递归肯定是不可信的更何况ets的赋值过程是位置的,这必然不保险。如果说我们使用定时间去调用咋一看是可以的,但是假设场景是你需要在handle中去创建一个新的EventSource或者Websocket,我们需要根据推送的数据去做展示,那么实时性是很难保证的,如果间隔过大很明显是不合理的,间隔过小和递归的区别意义不大,所以监听是更好的选择。

看了上面的代码不知道大家有没有发现一个问题,那就是我第一次获取导入的ets的值是在什么时候?很明显是componentDidMount也就是组件挂载完毕的时候对吧,但是如果是解构的话为什么递归以后会拿到在sse.js文件赋的值呢?

看下面的例子:

let obj1 = {
    a:1,
    b:2,
    c:0,
    add(){this.c = this.a + this.b + this.c}
}
let {a,b,c,add}= obj1

我创建了一个obj1的对象然后解构赋值,这个时候我们初始化打印试试:
在这里插入图片描述
这里的初始值都是0,接下来我分别调用obj1的add方法和解构后的方法看看结果:
在这里插入图片描述在这里插入图片描述

这里可以很明显的看到,解构出来的值都是独立之前的值的,这里解构更多的像是一种赋值。

那回过头来看我们的案例里面的etc这个值,在最开始componentDidMount中拿到的etc毋庸置疑是undefined,更新etc的值的方法只在sse.js文件中存在,那么为什么我们在递归到etc有值的时候能正确的拿到etc的值呢?用上面解构的逻辑按理来说我们无论如何拿到的都是etc的初始值也就是undefined

结论

很明显,我们能得出一个结论:ESmodule的导入并不等同于解构尽管写法和现象都非常相似。

我们可以认为解构就是一个赋值的过程,而模块导入是将导入的值放在了一个对象中,我们导入使用值的时候更多的是像使用这个对象的某一个属性,当这个对象的值被更改时我们使用的值也同样被更改了。这一点其实有点像基本数据和引用类型的数据的区别,可以大致参考这个模板去理解,如果知道js基本数据和引用类型数据的各种特点应该能很好的get到这点

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

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

相关文章

[echarts] legend icon 自定义的几种方式

echarts 官方配置项 地址 一、默认 图例项的 icon circle, rect, roundRect, triangle, diamond, pin, arrow, none legend: {top: 5%,left: center,itemWidth: 20,itemHeight: 20,data: [{icon: circle, name: 搜索引擎},{icon: rect, name: 直接访问},{icon: roundRect, n…

分布式系统---MapReduce实现(Go语言)

一、说明 本次实验是基于MIT-6.824的课程,详情请参见官网主页下载源代码 二、MapReduce原理 2.1 经典的分布式模型 MapReduce是经典的分布式模型。通过Map函数和Reduce函数实现。 分布式计算,就是利用多台机器,完成一个任务。关于分布式…

算法第一天力扣---2651. 计算列车到站时间

1.题目要求: 给你一个正整数 arrivalTime 表示列车正点到站的时间(单位:小时),另给你一个正整数 delayedTime 表示列车延误的小时数。 返回列车实际到站的时间。 注意,该问题中的时间采用 24 小时制。 示…

让ChatGPT猜你喜欢——ChatGPT后面的推荐系统

Chat GPT的大热,让人们的视线又一次聚焦于“人工智能”领域。通过与用户持续对话的形式,更加丰富的数据会不断滚动“雪球”,让Chat GPT的回答变得越来越智能,越来越接近用户最想要的答案。ChatGPT能否颠覆当下的推荐系统范式&…

第三章 灰度变换与空间滤波

第三章 灰度变换与空间滤波 3.1背景知识 ​ 空间域指图像平面本身。变换域的图像处理首先把一幅图像变换到变换域,在变换域中进行处理,然后通过反变换把处理结果返回到空间域。空间域处理主要分为灰度变换与空间滤波。 3.1.1 灰度变换和空间滤波基础 …

cmcc_simplerop

1,三连 2,IDA分析 溢出点: 偏移:0x144(错误) 这里动态重新测试了一下偏移: 正确偏移:0x20 3,找ROP 思路: 1、找系统调用号 2、ROPgadget找寄存器 3、写入/bin/sh ROPgadget --binary simpler…

7-2使用Redis构建任务队列

目录 7-2使用Redis构建任务队列 第1关:先进先出任务队列 1、rpush/lpush命令:rpush(name,values[values…]) 2、blpop:blpop(keys, timeout)和 lpop/rpop:lpop(name) 删并返回删除值 3、lpushx/rpushx:lpushx(name…

使用CKKS全同态求近似倒数(近似乘法逆元)

求倒数的算法 两个数互为倒数,是说这两个数乘起来等1.比如a和b互为倒数,那么ab1. 5的倒数是0.2,我们可以很简单的求出来,但是如何在密文域中求一个数的倒数呢? 文章《An investigation of complex operations with …

C#自适应布局

注意事项:不要在Form1中添加任何布局,页面背景不设置图片 步骤: 1、在项目中添加AutoWindowsSize.cs类,内容如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Da…

2.2 掌握 NumPy 矩阵与通用函数

2.2 掌握 NumPy 矩阵与通用函数 2.2.1 创建NumPy矩阵创建NumPy矩阵矩阵的运算矩阵的属性 2.2.2 掌握ufunc函数1、常用的ufunc函数运算2、ufunc函数的广播机制 2.2.1 创建NumPy矩阵 创建NumPy矩阵 1、使用mat函数创建矩阵: matr1 np.mat(“1 2 3;4 5 6;7 8 9”) 2…

casbin轻量级的基于配置的授权框架

简介 Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。 Casbin提供了一个执行者 根据提供给执行者的策略和模型文件验证传入的请求。再根据对应的配置授权策略,验证请求判断释放那些行动。 在 Casbin 中, 访问控制模…

由于找不到vcomp140.dll无法继续执行代码,解决方法全攻略

如何解决找不到vcomp140.dll错误?在使用某些软件或者游戏的时候,你可能会遇到下面的错误提示:“由于找不到vcomp140.dll,无法继续执行代码”。这个错误提示通常表示你的电脑缺少一个或多个DLL文件,而这些文件是软件和游…

「字节跳动测试开发面经」一二三面+hr面+超级全资料+复习资料

​ 说在前面,面试时最好不要虚报工资。本来字节跳动是很想去的,几轮面试也通过了,最后没offer,自己只想到几个原因: 1、虚报工资,比实际高30%; 2、有更好的人选,这个可能性不大&am…

【Linux】软件包管理器 yum和编辑器-vim的基本使用

文章目录 一、yum背景知识1.商业生态2.开源生态3.Linux软件生态本土化 二、yum的基本使用1.什么是软件包2.查看软件包3.安装软件4.卸载软件5.rzsz 三、vim的基本使用1.vim的基本概念2.vim的基本操作3.vim命令模式命令集4.vim末(底)行模式命令集5.操作总结 四、简单vim配置1.vim…

C++学习day--10 条件判断、分支

1、if语句 if 语句的三种形态 形态1&#xff1a;如果。。。那么。。。 #include <iostream> using namespace std; int main( void ) { int salary; cout << " 你月薪多少 ?" ; cin >> salary; if (salary < 20000) { cout <&…

浅谈整除分块

例题一 ∑ i 1 n ⌊ n i ⌋ \sum_{i1}^n \lfloor\frac n i\rfloor\\ i1∑n​⌊in​⌋ 首先很容易想到直接求解&#xff0c;对于较大的数据&#xff0c; O ( n ) O(n) O(n)做法无法通过。 注意到函数 y ⌊ n x ⌋ y\lfloor\dfrac n x\rfloor y⌊xn​⌋的图像如下&#xff1a…

Hive语言

一、Hive的DDL语言&#xff08;数据库、数据表的增删改查操作) 二、Hive的DQL语言&#xff08;数据库查询语言&#xff09; 2.1Hive七子句 聚合函数&#xff1a;count()、sum()、max()、min()、avg()可以单独使用。(缩写&#xff1a;cs mm a) 2.1.1 分区查询与分区裁剪 SELEC…

OpenGL(九)——颜色

目录 一、前言 二、简单光源 三、光照场景 3.1 创建光源 3.2 光源顶点着色器 3.3 光源片段着色器 3.4 物体片段着色器 3.5 光源位置 一、前言 我们看到的物体颜色是通过光照在物体&#xff0c;然后反射到人眼成像&#xff0c;具体而言是物体不能吸收的颜色。如白光照射…

C++学习day--09 字符串比较、运算符

1、项目练习 第 1 节 项目需求、项目实现 项目实现&#xff1a; #include <iostream> #include <Windows.h> #include <string> using namespace std; int main( void ) { string name; string pwd; std::cout << " 请输入账号&am…

GPT-4的免费使用方法分享

目录 方法1&#xff1a;使用Ora.sh的LLM应用 方法2&#xff1a;使用https://steamship.com 方法3&#xff1a;使用https://nat.dev 方法4&#xff1a;http://tdchat.vip 方法5&#xff1a;使用Poe网站或App 方法6&#xff1a;使用 Opencat App 方法7:使用https://Huggin…