React diff算法
看到后觉得加深了理解:组件只不过是一段Html结构的包装容器,并且具备管理这段Html结构的状态等能力。
React diff 是Virtual DOM 的加速器,具体问题就是计算一棵树形结构转换成另一棵树形结构的最少操作。
三个策略:
- 基于三个策略:
-
Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。(tree diff)
一种忽略跨层的先设前提,牺牲一些开发自由度来获取算法的高效性。
**开发建议:**保持稳定的 DOM 结构会有助于性能的提升。
-
拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结(component diff)
不同类直接构建重建,这里是基于我们开发时组件封装组件之间的差异性较大而提出来的。
**开发建议:**封装组件的时候要思考,为什么要封装它,它很独特吗,要是它有相似的兄弟呢,有的话为什么不尝试下合并呢
-
同父类组件:对于同一层级的一组子节点,它们可以通过唯一 id 进行区分。(element diff)
这让我联想到了,实际开发时渲染react数组数据的时候增加key属性。
**开发建议:**在开发过程中,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。
对这三个策略理解的不是很好,然后看到一张图:
这是react状态改变之后对应不同的组件类型进行的一个节点更新,其中有三种:文本、Dom、组件;
这里文本直接比较即可,组件则交由component(shouldComponentUpdate方法+策略一)去管理更新,重点是基本元素Dom
- 更新属性,对比出前后属性的不同,局部更新。并且处理特殊属性,比如事件绑定。
- **(重点:算法实现处)**子节点的更新,子节点更新主要是找出差异对象,找差异对象的时候也会使用上面的shouldUpdateReactComponent来判断,如果是可以直接更新的就会递归调用子节点的更新,这样也会递归查找差异对象。不可直接更新的删除之前的对象或添加新的对象。之后根据差异对象操作dom元素(位置变动,删除,添加等)。
算法:
插入,移动,删除:
流程:
设置一个lastIndex属性两个数组最远遍历到哪里了
lastIndex=0
- B(0):通过key发现旧的有B(1),lastIndex=1
- A(1):通过key发现旧的有A(0),lastIndex不变,但是0<1,需要移动A节点到1(当前)处,此时B就被动调整到了0的位置。
- D(2):通过key发现旧的有D(3),lastIndex=3
- C(3):通过key发现旧的有C(2),lastIndex不变,但是2<3,需要移动C节点到3(当前)处,此时D就被动调整到了2的位置。
再来一道:
-
B(0):旧的B(1),lastIndex=1
-
E(1):旧数组中不存在!此时增加E至数组(当前位置1)
-
C(2):旧的C(2),lastIndex=2
-
A(3):旧的A(0),0<2,进行移动,将A移动至3(当前)
此时我们可以看到旧数组是BECAD这样的结构,明显最后还需要有一次筛选的过程把旧数组中现在不存在的删除就ok了
参考文章链接:https://segmentfault.com/a/1190000016539430?utm_medium=referral&utm_source=tuicool
segmentfault.com/a/1190000016539430?utm_medium=referral&utm_source=tuicool