携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
在处理完entires之后,我们再看一下values与keys这两个方法,顾名思义,这两个方法一个是获取值的,一个是获取键名的.
对于values来讲,实现比较简单,几乎与上一章的一模一样。我们只需要把const iterator = target[Symbol.iterator]() 改成const iterator = target.values() 就可以了,一个是调用迭代器,一个是调用values方法,二者区别并不大。
略微有点麻烦的的是keys方法,如果按照我们实现values的来看,我们仍旧只是需要把const iterator = target.values()这句话改成const iterator = target.keys()应该就可以了.
大概代码如下,当next返回的时候,我们无需在处理键值对了,因为values与keys返回都是一个值而不是键值对。
如果我们运行图中这段代码,你会发现一个文档,当你修改值的时候,副作用函数还是执行了
const p = reactive(new Map([['a',1]]))
effect(()=>{
for(const k of p.keys()){
console.log(k)
}
})
p.set('a',2)
我们现在响应的是keys,也就是键名,但是现在是键值改变了,'a'是没有变了,但是副作用还是执行了,这就是多余的,这是为什么呢?
在前文说过,我们在trigger,也就是触发响应的时候,把遍历与ITERATE_KEY关联了起来,对于绝大多数情况,都是适用的比如entires和values,但是对于特殊的keys就不需要了。
作者解决的方法也不难,首先,换一个追踪的key,以前是ITERATE_KEY,这个key被用的太多了,我们重新命名一个
const MAP_KEY_ITERATE_KEY = Symbol()这个key仅用于追踪keys方法,其他方法还是ITERATE_KEY。
那么什么时候需要重新触发这个MAP_KEY_ITERATE_KEY追踪的依赖呢,仅当ADD,DELETE时才需要,这样SET的时候就不会响应了,就避免了我们上面那段代码的问题。