Reconciliation对账(DIFF算法)
为了解决dom的频繁reflow问题,对账 是一种对虚拟Dom的启发式比较算法,旨在对原始虚拟dom和更新后的虚拟dom进行比较,查找需要真正进行更新的节点和属性,解决dom的复用和操作问题,从而实现高效的重渲染更新。
React 的启发式算法在浏览器/HTML 已经给出的结构约束和性能边界之内,人为设计了一套工程上可接受的近似算法;它既利用了 HTML 的层级、顺序、key 等现成信息,也主动放弃了跨层移动、最少操作等理论上更优但复杂度高的方案。(复杂度仅为O(n))。
启发式假设:
- 两个不同类型的元素产生不同的树(基于树的对比)。 不同类型的节点会被算法否定,从而直接重建该元素以及此元素下面的所有子元素,即两棵树只对同一层次的节点进行比较,如果发现节点已经不存在了,则该节点及其子节点会被完全删除掉,不会用于进一步的比较,这就提升了比对效率。这个特性忽略节点跨层级操作场景,提升了比对效率。
- 可在兄弟节点中显式指定唯一字段
key来保证是稳定不被重建的。
1. 当兄弟节点被赋予key后,react会直接通对key进行对比,筛选出同层级中新增的key,对已有的key保持不变。key 只在“兄弟范围”内唯一即可
2.key能保证节点不被销毁重建,但如果它在兄弟列表中的相对顺序变了,React 仍会把 DOM 节点移动到新位置,这一步是同步 DOM 操作,不是重建。
3.key应当是稳定、可预测且唯一的, 不能使用Math.random()这种随机数来生成key,这样会导致每次重渲染都会生成不同新key,react会每次重建这个组件