Open unbrain opened 2 years ago
最开始一直比较迷惑的是为啥采取的是 target -> key -> fn 使用 targetsMap depsMap 最后获取 dep;
后面看了霍春阳的 《vue.js设计与实现》逐渐领悟了yyx写代码的深意
ecffect(()=>{
a = b.number + 1;
})
这段代码存在三个角色
如果用 target 来表示一个代理对象所代理的原始对象,用 key 来表示被操作的字段名,用 effectFn 来表示被注册的副作用函数,那么可以为这三个角色建立如下关系:
01 target
02 └── key
03 └── effectFn
那如果两个副作用同时读取同一个值
01 effect(function effectFn1() {
02 obj.text
03 })
04 effect(function effectFn2() {
05 obj.text
06 })
那么树形结构应当为
01 target
02 └── text
03 └── effectFn1
04 └── effectFn2
如果一个副作用函数中读取了同一个对象的两个不同属性:
01 effect(function effectFn() {
02 obj.text1
03 obj.text2
04 })
那么树形结构应当为
01 target
02 └── text1
03 └── effectFn
04 └── text2
05 └── effectFn
如果不同副作用函数中读取了不同对象的两个不同属性:
01 effect(function effectFn1() {
02 obj1.text1
03 })
04 effect(function effectFn2() {
05 obj2.text2
06 })
那么关系如下
01 target1
02 └── text1
03 └── effectFn1
04 target2
05 └── text2
06 └── effectFn2
Reactive Effect
响应式的方便在于能够自动去执行一些程序员设定好的函数
所以到了 vue 里面我们的写法就是
这里使用到了两个 vue 导出的
reactive
以及effect
我们分别来实现下Reactive
使用TDD,我们期望达到的效果,先写单测代码
实现:
此时多出来两个函数分别是依赖收集与依赖触发。
一个数据一旦被取值,那么他就需要被依赖收集 以便当有副作用时能够被触发。而一个值被重新赋值了那么他的副作用需要自动执行。
1.触发收集一定是在Effect中出现的,所以将track放在 effect 中
2.依赖触发其实就是再次执行传入的effect中的函数,所以也放在 effect 代码中实现
我们在最后讨论这两函数的实现
Effect
TDD 我们期望运行后 effect 会被默认执行一次
我们先写个大致形式
此时 effect 已实现了自动执行一次
我们再来思考如何收集依赖
track 副作用收集
副作用调用
scheduler
看下 vue 测试代码
1.默认执行 run 不执行 scheduler 副作用时粗发 不执行 run 执行 scheduler
2.effct 返回的将是一个函数