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

【Vue3源码】第二章 effect功能的完善补充

【Vue3源码】第二章 effect功能的完善补充

前言

上一章节我们实现了effect函数的功能stop和onstop,这次来优化下stop功能。

优化stop功能

之前我们的单元测试中,stop已经可以成功停止了响应式更新(清空了收集到的dep依赖)

stop功能其实还存在很大的问题,就是不能停止对象中的++操作

为什么呢?

看个例子

let user = { age : 10 }user.age++
//++是一个语法糖,他在js中的表现为
//user.age = user.age + 1

看了例子我们就可以明白为什么stop功能会存在漏洞了,因为user.age = user.age + 1 这句代码在响应式中user.age + 1会先触发get捕获器然后 +1触发set捕获器

那么get捕获器又会重新收集依赖,我们之前stop清空的依赖就又回来了导致无法stop响应式更新这个漏洞出现

怎么解决这个问题?

我们可以从run方法和track函数切入,只要判断调用run方法track就去收集依赖,如果是stop调用的run方法,track函数就不要去收集依赖即可。

1.单元测试代码

进入effect.spec.ts文件

还是使用之前的stop单元测试代码即可

我们把obj.prop = 3 改为 obj.prop++

 it("stop",() => {let dummy;const obj = reactive({prop:1})const runner = effect(() => {dummy = obj.prop})obj.prop = 2expect(dummy).toBe(2)stop(runner)// 修改// obj.prop = 3obj.prop++expect(dummy).toBe(2)//stopped effect should still be manually callablerunner()expect(dummy).toBe(3)})

2.优化run方法

进入effect.ts文件

我们再通过新增一个全局变量shouldTrack,作为开关,去有效的控制track进行依赖收集

//新增
let shouldTrack;class ReactiveEffect {private _fn;active = true;deps = [];onStop?: () => void;constructor(fn, public scheduler?) {this._fn = fn;this.scheduler = scheduler;}//修改run() {// 3.因为默认shouldTrack= false// 4.调用了stop的时候直接执行了this._fn()// 5.但是shouldTrack是关上的if (!this.active) {return this._fn()}// 1.run的时候才会开启开关shouldTrack = true;activeEffect = this;const result = this._fn();// 2.reset,生成ReactiveEffect类时,我们都会默认调用 _effect.run()方法,所以默认执行完this._fn()后都会重置 shouldTrack = falseshouldTrack = false;return result}stop() {if (this.active) {clearupEffect(this);if (this.onStop) {this.onStop()}this.active = false}}
}

调用run()方法的时候会去开启shouldTrack开关,因为生成ReactiveEffect类时我们都会默认调用 _effect.run()方法,所以默认的 this._fn()执行完后都会使shouldTrack 重置为 shouldTrack = false

在这里插入图片描述

那么就出现以下两种情况:

正常调用effect.run() 和 stop调用 effect.run()

他们通过shouldTrack这个开关就可以识别,所以我们可以通过shouldTrack全局变量去判断track是否该触发依赖收集

3.优化track函数

vue3源码就是通过shouldTrackactiveEffect两个开关去控制track函数执行,来达到可以控制的依赖收集功能

//依赖收集
export function track(target, key) {// 6.如果是stop调用那么在触发track时,因为shouldTrack是false,所以track就不能执行了// 7.如果是run()调用那么在触发track时,因为shouldTrack是true,所以可以执行track逻辑,等track结束,才把shouldTrack = falseif (activeEffect && shouldTrack) {let depsMap = targetMap.get(target);if (!depsMap) {depsMap = new Map();targetMap.set(target, depsMap);}let dep = depsMap.get(key);if (!dep) {dep = new Set();depsMap.set(key, dep);}dep.add(activeEffect);//浅拷贝反向收集到depactiveEffect.deps.push(dep);}
}

4.优化clearupEffect函数

用for代替了forEach提高性能,如果清空了依赖我们就把deps的length也清空,最大程度的优化性能

function clearupEffect(effect) {const { deps } = effectif (deps.length) {for (let i = 0; i < deps.length; i++) {//因为是浅拷贝收集到的dep,所以这里删掉对应的dep就没有了,没有dep(二级分类)自然就无法触发run方法!deps[i].delete(effect)}deps.length = 0}
}

5.代码运行流程图

上面就基本把stop的漏洞修复了,我们来看下run方法运行和stop方法运行时的区别

在这里插入图片描述
通过所有测试!
在这里插入图片描述

相关文章:

【Vue3源码】第二章 effect功能的完善补充

【Vue3源码】第二章 effect功能的完善补充 前言 上一章节我们实现了effect函数的功能stop和onstop&#xff0c;这次来优化下stop功能。 优化stop功能 之前我们的单元测试中&#xff0c;stop已经可以成功停止了响应式更新&#xff08;清空了收集到的dep依赖&#xff09; st…...

CHAPTER 2 Web Server - apache(httpd)

Web Server - httpd2.1 http2.1.1 协议版本2.1.2 http报文2.1.3 web资源(web resource)2.1.4 一次完整的http请求处理过程2.1.5 接收请求的模型2.2 httpd配置2.2.1 MPM(多进程处理模块)1. 工作模式2. 切换MPM3. MPM参数配置2.2.2 主配置文件1. 基本配置2. 站点访问控制常见机制…...

【Vagrant】下载安装与基本操作

文章目录概述软件安装安装VirtualBox安装Vagrant配置环境用Vagrant创建一个VMVagrantfile文件配置常用命令概述 Vagrant是一个创建虚拟机的技术&#xff0c;是用来创建和管理虚拟机的工具&#xff0c;本身自己并不能创建管理虚拟机。创建和管理虚拟机必须依赖于其他的虚拟化技…...

常用类(五)System类

(1)System类常见方法和案例&#xff1a; &#xff08;1&#xff09;exit:退出当前程序 我们设计的代码如下所示&#xff1a; package com.ypl.System_;public class System_ {public static void main(String[] args) {//exit: 退出当前程序System.out.println("ok1"…...

Navicat Premium 安装 注册

Navicat Premium 一.Navicat Premium的安装 1.暂时关闭windows的病毒与威胁防护弄完再开&#xff0c;之后安装打开过程中弹窗所有警告全部允许,不然会被拦住 2.下载安装包&#xff0c;解压 链接&#xff1a;https://pan.baidu.com/s/1X24VPC4xq586YdsnasE5JA?pwdu4vi 提取码…...

回溯算法总结

首先回溯算法本身还是一个纯暴力的算法&#xff0c;只是回溯过程可能比较抽象&#xff0c;导致大家总是感觉看到的相关题目做的不是很顺畅&#xff0c;回溯算法一般来说解决的题目有以下几类&#xff1a;组合问题&#xff1a;lq77、lq17、lq39、lq40、lq216、切割问题&#xff…...

ccc-pytorch-基础操作(2)

文章目录1.类型判断isinstance2.Dimension实例3.Tensor常用操作4.索引和切片5.Tensor维度变换6.Broadcast自动扩展7.合并与分割8.基本运算9.统计属性10.高阶OP大伙都这么聪明&#xff0c;注释就只写最关键的咯1.类型判断isinstance 常见类型如下&#xff1a; a torch.randn(…...

独居老人一键式报警器

盾王居家养老一键式报警系统&#xff0c;居家养老一键式报警设备 &#xff0c;一键通紧急呼救设备&#xff0c;一键通紧急呼救系统&#xff0c;一键通紧急呼救器 &#xff0c;一键通紧急呼救终端&#xff0c;一键通紧急呼救主机终端产品简介&#xff1a; 老人呼叫系统主要应用于…...

软考案例分析题精选

试题一&#xff1a;阅读下列说明&#xff0c;回答问题1至问题4&#xff0c;将解答填入答题纸的对应栏内。某公司中标了一个软件开发项目&#xff0c;项目经理根据以往的经验估算了开发过程中各项任务需要的工期及预算成本&#xff0c;如下表所示&#xff1a;任务紧前任务工期PV…...

基于SpringBoot+vue的无偿献血后台管理系统

基于SpringBootvue的无偿献血后台管理系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背…...

详解js在事件中,如何传递复杂数据类型(数组,对象,函数)

文章目录 前言一、何谓预编译&#xff0c;变量提升&#xff1f;二、复杂数据类型的传递 1.数组2.对象3.函数总结前言 在JavaScript这门编程语言学习中&#xff0c;如何传参&#xff0c;什么是变量提升&#xff0c;js代码预编译等等。要想成为一名优秀的js高手&#xff0c;这些内…...

高并发架构 第一章大型网站数据演化——核心解释与说明。大型网站技术架构——核心原理与案例分析

大型网站架构烟花发展历程1.1.1初始阶段的网站构架1.1.2应用服务和数据服务分离1.1.3使用缓存改善网络性能1.1.4使用应用服务器集群改善网站的并发处理能力1.1.5数据库读写分离1.1.6使用反向代理和cdn加速网站相应1.1.1初始阶段的网站构架 大型网站都是由小型网站一步步发展而…...

VPP接口INPUT节点运行数据

在设置virtio接口接收/发送队列函数的最后&#xff0c;更新接口的运行数据。 void virtio_vring_set_rx_queues (vlib_main_t *vm, virtio_if_t *vif) { ...vnet_hw_if_update_runtime_data (vnm, vif->hw_if_index); } void virtio_vring_set_tx_queues (vlib_main_t *vm,…...

RabbitMQ学习(九):延迟队列

一、延迟队列概念延时队列中&#xff0c;队列内部是有序的&#xff0c;最重要的特性就体现在它的延时属性上&#xff0c;延时队列中的元素是希望 在指定时间到了以后或之前取出和处理。简单来说&#xff0c;延时队列就是用来存放需要在指定时间内被处理的 元素的队列。其实延迟…...

TCP并发服务器(多进程与多线程)

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 TCP并发服务器&#xff08;多进程与多线程&#xff09;1. 多进程并发服务器&#xff08;1&#xff09;…...

第1章 Memcached 教程

Memcached是一个自由开源的&#xff0c;高性能&#xff0c;分布式内存对象缓存系统。 Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素…...

【2022.12.9】Lammps+Python 在计算g6(r)时遇到的问题

目录写在前面绘制g6( r )执行步骤【updated】如何检查图像的正确性&#xff1a;不是编程问题&#xff0c;而是数学问题的一个小bug废稿2则&#xff1a;写在前面 全部log&#xff1a; 【2022.11.16】LammpsPythonMATLAB在绘制维诺图时遇到的问题 绘制g6( r )执行步骤【updated…...

MySQL使用C语言连接

文章目录MySQL使用C语言连接引入库下载库文件在项目中使用库使用库连接数据库下发SQL请求获取查询结果MySQL使用C语言连接 引入库 要使用C语言连接MySQL&#xff0c;需要使用MySQL官网提供的库。 下载库文件 下载库文件 首先&#xff0c;进入MySQL官网&#xff0c;选择DEVEL…...

JavaScript随手笔记---比较两个数组差异

&#x1f48c; 所属专栏&#xff1a;【JavaScript随手笔记】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#…...

【C++修炼之路】21.红黑树封装map和set

每一个不曾起舞的日子都是对生命的辜负 红黑树封装map和set前言一.改良红黑树的数据域结构1.1 改良后的结点1.2 改良后的类二. 封装的set和map2.1 set.h2.2 map.h三. 迭代器3.1 迭代器封装3.2 const迭代器四.完整代码实现4.1 RBTree.h4.2 set.h4.3 map.h4.4 Test.cpp前言 上一节…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...