zoukankan      html  css  js  c++  java
  • Vue3源码系列之依赖收集的实现

    effect
    effect方法是响应式的核心,叫做副作用函数。初始会默认执行时会进行取值操作,只要取值就会调用get方法,我们就可以将对应的effect函数存放起来,等会我们去更新effect函数内部所依赖的状态数据时,就去调用一开始存对应的effect函数,视图就进行了更新
     
    注:state与effect有关联,只有对应的数据变了,对应的effect才会执行
     
    核心原理
     
    第一步
    创建effect.ts文件,导出effect方法,内部依靠一个创建响应式的方法createReactiveEffect,外层做格式化,内层做响应式。
    注:内部返回的effect是一个函数
     
    根据第二个参数选项项中的lazy属性判断,如果不是非trueeffect默认会先执行一次
     
     
    第二步
    开始编写createReactiveEffect的逻辑
     
    • 我们需要给effect加一个唯一标识,方便追踪这是哪个地方属于谁的的effect
      • 在外面做一个序号uid,每次调用createReactiveEffect,就给创建出来的effect加一个标识id,值为uid++
    • 我们需要再给effect加一个_isEffect标识,用于标识这个是响应式effect,值为true,下划线字段标识私有的
    • 我们还需要记录一下effect对应的原本的函数是谁,raw = fn
    • 我们再把选项也保存起来
           
     
     
    第三步
    刚才我们说到,effect会根据选项初始默认执行一次,那么我们先在reactiveEffect函数里让fn执行一次,也就是用户传入的函数
     
     
    用户调用的时候effect的时候会进行取值,那一取值就会触发该属性的get方法,走到对应的hanlders里。之前我们说到,vue3的代理模式的惰性的。所以我们在此时进行依赖收集,收集effect
     
    第三步
    在reactive里进行依赖收集,也就是回到上一篇文章的最后地方。
     
    首先我们在createrGetter里写一个track方法进行依赖收集,而这个track方法写在了effect文件里,将方法导出,reactive文件 里进行引入
     
    • 我们需要告诉tract哪个对象,什么操作?哪个属性
    • 新建一个文件operators.ts专门用于放操作符的
      •    
     
     
    现在我们去写track
    问题:我们怎么在track里拿到对应的effect呢?
     
    答案就是全局变量,利用全局变量就关联起来了
     
    问题一:我们可能写出这样的代码
    它会取最后一个,这就乱了,去address,effect应该还是effect1

    所以我们可以弄栈型结构来处理,来保证每个属性收集的effect是正确的
     
    每次执行的时候入栈,然后把当前的effect保存到全局变量,然后调用用户传的函数,最后执行完了,再把effect出栈,然后取当前栈中最后一个赋给全局变量,也就是执行完再赋值回去。
     
    这样操作就保证了effect顺序,在track中取到的effect是正确的
     
    问题二:我们可能写出这样的代码
    就死循环了,会不停的刷新
     
    所以我们在放入栈的时候,先看看这个effect是不是已经在栈里了
     
    综上:我们就实现了让某个对象中的属性收集当前他对应的effect函数
     
    第四步
    一个对象的属性是有可能对应多个effect的,所以我们现在要用一种数据结构给他俩关联起来
    我们可以用weakMap来进行关联
     
    在外面new 一个WeakMap
     
    如果activeEffect等于undefined,则表示没在effect中使用
     
    然后进行关联
     
    解析:
    • 先去target里取值,第一次取肯定是undifined
    • 如果没取到,那我就往这里面放,key是这个target,第二次参数就是个map,这个新new的map同时又赋值给当前的depsMap
    • 再从targetMap进行取值,看看没有依赖收集
    • 如果没有,往当前的map里设置进去,进行依赖收集,值设置成一个set
    • 如果当前取的set中没有当前的activeEffect,那就往当前的set中把依赖添加进去,由此可见,依赖是收集在了最后的set数据结构中
    • 有点绕,最后映射出来的结构大概是这个样子
     可能有人有对用weakMap和map没啥疑问,但是对最后的set数据解决进行存储effect有疑问,为啥最后那里要用set来存储effect呢?
    • 答案如果你在effect内对一个对象取了多次,那么如果没有用set,这个属性你就保存了多个相同的effect,是这个道理吧
    博主掘金技术社区地址——https://juejin.cn/user/1908407918660871/posts
  • 相关阅读:
    Capture CIS:Capture was not found错误
    Memcached FAQ
    MTK META工具的使用和注意事项(MT6252)
    关于maps.google.com和ditu.google.cn地图偏差的说明
    VSS2005的二次开发
    同学PB经历的面试题
    给定一个字符串,包含中文字符和英文字符,取给定大小字节的子串。
    一些笔试题目和整理的答案 腾讯(Tencent)
    redhat面试题目
    Ubuntu远程链接Ubuntu之ssh
  • 原文地址:https://www.cnblogs.com/tengfeiS/p/15251738.html
Copyright © 2011-2022 走看看