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

Vue.js---分支切换与cleanup

4.2 分支切换与cleanup

1、分支切换

01 const data = { ok: true, text: 'hello world' }
02 const obj = new Proxy(data, { /* ... */ })
03
04 effect(function effectFn() {
05   document.body.innerText = obj.ok ? obj.text : 'not'
06 })

什么是分支切换?就是

document.body.innerText = obj.ok ? obj.text : 'not'

但是这就会导致一个问题“可能会产生遗留的副作用函数”

eg:当obj.ok的值为false的时候,obj.text不会被读取,只会触发obj.ok的读取操作。所以effectFn不应该被obj.text所收集在这里插入图片描述

但是我们目前还是会遗留副作用函数,导致一些不必要的更新

如何解决???

3、清除函数

每次副作用函数执行时,我们可以先把它从所有与之关联的依赖集合中删除

在这里插入图片描述

当副作用函数执行完之后会重新建立连接,但在新的连接中是不会包含遗留的副作用函数的

大概思路:在 effect 内部我们定义了新的 effectFn 函数,并为其添加了 effectFn.deps 属性,该属性是一个数组,用来存储所有包含当前副作用函数的依赖集合。

设置deps属性:

 function effect (fn) {const effectFn = () => {// 当其执行时,将其设置为当前激活的副作用函数activeEffect = effectFn; fn();}// deps用来存储所有与该副作用函数相关联的依赖集合effectFn.deps = [];// 执行副作用函数effectFn();}

建立依赖集合与effectFn的联系

  function track(target , key){if(!activeEffect){return target[key];}// 根据tartget取来的depsMap,它是一个map类型let depsMap = bucket.get(target);// 如果不存在if(!depsMap){// 创建一个bucket.set(target, (depsMap = new Map()));}// 根据key取来的deps,它是一个set类型let deps = depsMap.get(key);// 如果不存在if(!deps){// 创建一个depsMap.set(key, (deps = new Set()));}deps.add(activeEffect); // 添加当前活跃的副作用函数// 存储存在联系的依赖集合,建立起依赖集合和effectFn的关系deps.add(activeEffect);// deps就是一个与当前副作用函数存在联系的依赖集合// 把它存在activeEffect里面的deps中activeEffect.deps.push(deps);}

开始一个个删除联系

  function effect (fn) {const effectFn = () => {// 调用clearup函数完成清除工作clearUp(effectFn);// 当其执行时,将其设置为当前激活的副作用函数activeEffect = effectFn; fn();}// deps用来存储所有与该副作用函数相关联的依赖集合effectFn.deps = [];// 执行副作用函数effectFn();}
   // 清除函数function clearUp (effectFn){// 遍历然后进行删除for(let i = 0 ; i < effectFn.deps.length ; i++){const deps = effectFn.deps[i];// 移除deps.delete(effectFn);}// 最后重置effectFn.deps数组eff.deps.length = 0;}

我们的清除遗留副作用函数就大功告成啦!但是为什么一直死循环!!?

问题在trigger函数当中

  // 触发变化function trigger(target , key , newVal){const depsMap = bucket.get(target);if(!depsMap){return;}const effects = depsMap.get(key);effects && effects.forEach(fn => fn()); // 只触发与键相关的副作用函数}

在这个函数中,我们遍历effects集合,当副作用函数执行的时候会调用clearUp函数清除,实际上就是从effects集合中将当前执行的副作用函数剔除,但是副作用函数的执行又会导致其重新被收集到集合中,陷入死循环。

如何解决?新构造一个集合并遍历它,代替直接遍历effects函数,就不会出现这样的问题啦

  // 触发变化function trigger(target, key, newVal) {const depsMap = bucket.get(target);if (!depsMap) {return;}const effects = depsMap.get(key);const effectsToRun = new Set(effects);effectsToRun.forEach(effectFn => effectFn());// effects && effects.forEach(fn => fn()); // 只触发与键相关的副作用函数}

造一个集合并遍历它,代替直接遍历effects函数,就不会出现这样的问题啦

  // 触发变化function trigger(target, key, newVal) {const depsMap = bucket.get(target);if (!depsMap) {return;}const effects = depsMap.get(key);const effectsToRun = new Set(effects);effectsToRun.forEach(effectFn => effectFn());// effects && effects.forEach(fn => fn()); // 只触发与键相关的副作用函数}

总结:解决分支问题,主要是clearUp函数在副作用函数执行前清除旧的依赖关系,确保只有当前实际使用的属性变化时才触发更新,值得注意的是我们遍历effects集合,当副作用函数执行的时候会调用clearUp函数清除,实际上就是从effects集合中将当前执行的副作用函数剔除,但是副作用函数的执行又会导致其重新被收集到集合中,陷入死循环,我们要构造一个集合并遍历他

http://www.xdnf.cn/news/418285.html

相关文章:

  • 第六章 GPIO输入——按键检测
  • 工业4G路由器IR5000公交站台物联网应用解决方案
  • 游戏引擎学习第275天:将旋转和剪切传递给渲染器
  • 【Linux】简单设计libc库
  • Spring Boot之Web服务器的启动流程分析
  • Antd中Form详解:
  • Mapreduce初使用
  • 第四章 部件篇之按钮矩阵部件
  • 在Linux中使用 times函数 和 close函数 两种方式 打印进程时间。
  • 线代第二章矩阵第八节逆矩阵、解矩阵方程
  • 【计算机视觉】OpenCV项目实战:基于face_recognition库的实时人脸识别系统深度解析
  • 光谱相机的光电信号转换
  • 基于Java的家政服务平台设计与实现(代码+数据库+LW)
  • 游戏引擎学习第277天:稀疏实体系统
  • GNU Screen 曝多漏洞:本地提权与终端劫持风险浮现
  • 前端如何应对精确数字运算?用BigNumber.js解决JavaScript原生Number类型在处理大数或高精度计算时的局限性
  • SQL中联表的运用
  • OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——mqtt库
  • WSL 安装 Debian 12 后,Linux 如何安装 nginx ?
  • Boby家族之Smart Boby:你的智能编程助手
  • YOLOv11融合[AAAI2025]的PConv模块
  • [51单片机]---DS18B20 温度检测
  • 第六节第二部分:抽象类的应用-模板方法设计模式
  • vim 练习题
  • 苍穹外卖--新增菜品
  • 按键精灵ios脚本新增元素功能助力辅助工具开发(一)
  • 机器学习07-归一化与标准化
  • mybatis中${}和#{}的区别
  • 【RabbitMQ】工作队列和发布/订阅模式的具体实现
  • 微服务八股(自用)