携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情
这一章的大标题叫做非原始值的响应式方案。而非原生值,一般指的就是Object、Array、Map、Set这些,当然也包含WeakMap、WeakSet这些。这一章就是讲这些类型如果去响应,对于在vue3中,就是我们最常用的reactive.当然,最后也是输出了一个reactive,但这个实现问题还是很多的,只能算是一个demo.
Proxy与Reflect
我们都知道vue3中使用了Proxy,因此这一小节算是储备知识,而为了解决代理后this的指向问题,我们又引入了Reflect。其实日常使用中,这两个通常是成对出现的。
Javascript对象的探究
我们要学习响应式对象,就要对对象有深入的了解,在这一小节里,我觉得最重要的就是找到了EMCA文档,在这里面我能找到所有对象,所有js方法的具体描述,相当于一个需求文档一样。
代理Object
我们首先尝试去代理Object,主要实现了读取,修改,删除,以及遍历等。其中着重讲了一下遍历,最重要的是for ... in。
在这小节中,我们还重点关注了,如何合理的触发副作用函数,这个原则也贯穿了整张。多余的副作用执行不但对性能有影响,更是有可能导致程序的结果不正确。就好比我们有一个副作用函数i++,那么多执行一次,结果就错了。
这一张里还有学到了一个小tips,就是在对比值的时候要注意NaN,因为Nan===NaN永远为假。
在这一小节里,我们基本实现了一个reactive,在后续都会在这个reactive上去扩充。
深响应与浅响应,深只读与浅只读
这里其实都是对reactive,深响应其实就是递归对象,把里面每一个对象都转换为响应式。
只读 其实就是拦截修改操作,深只读其实就是递归对象,把里面每一个对象都转换为只读对象。
这一小节其实不难,稍微看下都没有问题
代理Array
数组与对象有着很多区别,因此这里重新修改reactive,并且稍微讨论一下includes\push\splice等这些方法的实现.
在代理数组的时候,我们碰到了一个堆栈溢出的问题,因为我们同时依赖了Array.length,在不同的副作用函数内对同一个数组执行上述方法,导致多个副作用之间的循环调用,最后导致爆栈。解决方法就是我们新增一个全局变量。
代理其他类型
这里的其他类型主要是指Map\Set\weakMap\wekeSet,这些类型里比较麻烦的是迭代的实现,要注意迭代器与迭代器协议的实现。
还有这一小节里提到了原始数据污染的问题,也值得仔细玩味。