当前位置: 首页 > 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集合中将当前执行的副作用函数剔除,但是副作用函数的执行又会导致其重新被收集到集合中,陷入死循环,我们要构造一个集合并遍历他

相关文章:

  • 门禁人脸识别系统详细技术文档
  • 使用聊天模型和提示模板构建一个简单的 LLM 应用程序
  • 论坛系统(中-1)
  • Excel宏和VBA
  • 【周输入】510周阅读推荐-1
  • Timsort 算法
  • Promise.all静态方法
  • 销量预测评估指标
  • Python Django基于模板的药品名称识别系统【附源码、文档说明】
  • OpenVLA (2) 机器人环境和环境数据
  • 浏览器打开多线程下载教程,加快下载速度,让你的下载速度有质的飞跃
  • 【Bluedroid】蓝牙 HID DEVICE 初始化流程源码解析
  • C++中的虚表和虚表指针的原理和示例
  • 人脸识别系统中的隐私与数据权利保障
  • Supabase 的入门详细介绍
  • 【datawhale 组队学习】task01 第一章LLM介绍
  • ESP32C3连接wifi
  • 【PmHub后端篇】PmHub中基于自定义注解和AOP的服务接口鉴权与内部认证实现
  • 主流高防服务器技术对比与AI防御方案实战
  • Docker常用命令及示例大全
  • 费高云不再担任安徽省人民政府副省长
  • 京东一季度净利增长五成,营收增速创近三年新高,称外卖业务取得显著进展
  • 时隔4年多,这一次普京和泽连斯基能见面吗?
  • 白玉兰奖征片综述丨综艺市场破局焕新,多元赛道重塑价值坐标
  • 特朗普将启的中东行会如何影响伊美核谈判?专家分析
  • 汉斯·季默:不会指挥的声音工程师终成音乐“大神”