diff算法是能够更加高效快捷更新页面元素的算法,那如何帮助diff更快呢?
那答案就一定是合理的使用key。
diff的调用是在reconcileChildren中的reconcileChildFibers,当没有可以复用current fiber节点时,就会走mountChildFibers,当有的时候就走reconcileChildFibers。
而reconcilerChildFibers的函数中则会针render函数返回的新的jsx数据进行判断,它是否是对象,就会判断它的newChild.$$typeof是否是REACT_ELEMENT_TYPE,如果是就按单节点处理。 如果不是继续判断是否是REACT_PORTAL_TYPE或者REACT_LAZY_TYPE。
继续判断它是否为数组,或者可迭代对象。
而在单节点处理函数reconcileSingleElement中,会执行如下逻辑:
- 通过
key,判断上次更新的时候的Fiber节点是否存在对应的DOM节点。 如果没有 则直接走创建流程,新生成一个 Fiber 节点,并返回 - 如果有,那么就会继续判断,
DOM节点是否可以复用?
<!---->
- 如果有,就将上次更新的
Fiber节点的副本作为本次新生的Fiber节点并返回
<!---->
- 如果没有,那么就标记
DOM需要被删除,新生成一个Fiber节点并返回。
React 是如何判断一个 Fiber 节点是否可以被复用的。
- 第一步:判断
element的key和fiber的key是否相同
<!---->
- 如果不相同,就会创建新的
Fiber,并返回
<!---->
- 第二步:如果相同,就判断
element.type和fiber的type是否相同,type就是他们的类型,比如p标签就是p,div标签就是div.如果type不相同,那么就会标识删除。
<!---->
- 如果相同,那就可以可以判断可以复用了,返回
existing。
而在多节点更新的时候,key的作用则更加重要,React 会通过遍历新旧数据,数组和链表来通过按个判断它们的key和 type 来决定是否复用。
言而总之,需要合理的使用key来加快diff算法的比对和fiber的复用。
那么如何合理使用key呢。
其实很简单,只需要每一次设置的值和我们的数据一直就可以了。不要使用数组的下标,这种key和数据没有关联,我们的数据发生了更新,结果 React 还指望着复用。










