我们先来看一个例子
- 第一次setTimeout执行,我们已经不依赖state上的name属性了,然后第二个setTimeout时我们又修改了state上的name属性
- 但是在转换前name收集了这个effect,转换后,age也收集了这个effect,当第二个setTimeout里更改了name属性后,又会重新的触发这个effect,重新渲染一次页面,这个时候就有问题了
所以我们期望的是每次执行effect的时候都可以清理一遍依赖,重新收集
- 也就是清理effect收集的dep,dep就是对象属性对应的那个Set,里面记录了该属性收集的effect,而effect上的deps又会反过来收集这些dep
- 在执行effect之前对deps进行清理操作
现在我们就来写这个cleanupEffect方法进行清理操作
- 首先我们先拿到当前执行的effect上的deps属性
- 然后循环拿到那些收集了当前effect的对象属性所收集的effect,也就是那个Set,然后把自己给删除掉,让那些收集了自己的对象属性不再收集自己
- 然后再让当前effect上的deps清空
- 简而言之就是再每次执行effect之前,清空那些收集了自己的对象属性和自己本身,然后再去执行effect,重新收集依赖
但是这样写呢,会出现死循环
- 我们在执行上述的this.fn的时候会重新设置state上的值,那么就会执行它所收集的依赖,然后又会先清空,然后再触发fn,这就陷入了死循环,类似于下面这种代码
所以再执行这些effect的时候我们就不要用老的effects了,判断用一个,循环用一个
修改成
- 我们我们在执行到当前effect的时候,会重新往effects里加,但是我们重新拷贝了一份执行之前的effects,这样就不会出现边循环,边删,边往里加了,也就不会陷入死循环了