dom-diff 是一个对比老的fiber链表和新的jsx 数组,生成新的fiber链表的过程:
如下
image.png
image.png

image.png

单节点

image.png

1.type不同

image.png

2.key和type都不同

image.png

3.type 和key 都一样

image.png

4.key相同但是type不同,直接删除所有老节点

image.png

多节点

image.png

1.一一对比,key 相同,type 相同,只需更新

image.png

2.一一对比,key 相同,type 不同,删除老的,添加新的

image.png

3.key 不同,退出第一轮循环

image.png
第一轮循环,A=A 能复用,更新A就可以,key 不一样,则马上跳出第一轮循环。

第二轮循环,建立map,key就是元素的key,值就是老的fiber节点
let map = {‘B’: B, ‘C’: C, ‘D’: D, ‘E’: E, ‘F’: F};
继续遍历新的节点,C找到会给C标记为更新,另外会从map中删除C,map 表示还没有被复用的fiber节点。
等新的jsx数组遍历完了之后,把map里的fiber节点全部删除,如下图:
image.png
先删除再更新

key机制

(1)key的作用
当同一层级的某个节点添加了key属性,当它在当前层级的位置发生了变化后。react diff算法通过新旧节点比较后,如果发现了key值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。这无疑大大提高了React性能和渲染效率

(2)index作为key
react中常常会用到通过遍历(如Array.map)来在当前层级动态生成多个子节点的操作。这是常见的列表数据渲染场景。
React官方建议不要用遍历的index作为这种场景下的节点的key属性值。比如当前遍历的所有节点类型都相同,其内部文本不同,在用index作key的情况下,当我们对原始的数据list进行了某些元素的顺序改变操作,导致了新旧集合中在进行diff比较时,相同index所对应的新旧的节点其文本不一致了,就会出现一些节点需要更新渲染文本,而如果用了其他稳定的唯一标识符作为key,则只会发生位置顺序变化,无需更新渲染文本,提升了性能