文档详情

React中的Diff算法你了解吗.docx

发布:2025-05-16约4.43千字共8页下载文档
文本预览下载声明

React中的Diff算法你了解吗

目录一、Diff算法的作用二、React的Diff算法1、什么是调和?2、什么是Reactdiff算法?3、diff策略4、treediff:5、componentdiff:6、elementdiff三、基于Diff的开发建议总结

一、Diff算法的作用

渲染真实DOM的开销很大,有时候我们修改了某个数据,直接渲染到真实dom上会引起整个dom树的重绘和重排。我们希望只更新我们修改的那一小块dom,而不是整个dom,diff算法就帮我们实现了这点。

diff算法的本质就是:找出两个对象之间的差异,目的是尽可能做到节点复用。

注:此处说到的对象,指的其实就是vue中的virtualdom(虚拟dom树),即使用js对象来表示页面中的dom结构。

二、React的Diff算法

1、什么是调和?

将VirtualDOM树转换成ActualDOM树的最少操作的过程称为调和。

2、什么是Reactdiff算法?

diff算法是调和的具体实现。

3、diff策略

React用三大策略将O(n3)复杂度转化为O(n)复杂度

(1)策略一(treediff):WebUI中DOM节点跨层级的移动操作特别少,可以忽略不计。

(2)策略二(componentdiff):拥有相同类的两个组件生成相似的树形结构,拥有不同类的两个组件生成不同的树形结构。

(3)策略三(elementdiff):对于同一层级的一组子节点,通过唯一id区分。

4、treediff:

(1)React通过updateDepth对VirtualDOM树进行层级控制。

(2)对树分层比较,两棵树只对同一层次节点进行比较。如果该节点不存在时,则该节点及其子节点会被完全删除,不会再进一步比较。

(3)只需遍历一次,就能完成整棵DOM树的比较。

如果DOM节点出现了跨层级操作,Diff会怎么办?

答:TreeDIFF是对树的每一层进行遍历,如果某组件不存在了,则会直接销毁。如图所示,左边是旧属,右边是新属,第一层是R组件,一模一样,不会发生变化;第二层进入ComponentDIFF,同一类型组件继续比较下去,发现A组件没有,所以直接删掉A、B、C组件;继续第三层,重新创建A、B、C组件。

如上图所示,以A为根节点的整棵树会被重新创建,而不是移动,因此官方建议不要进行DOM节点跨层级操作,可以通过CSS隐藏、显示节点,而不是真正地移除、添加DOM节点。

5、componentdiff:

React对不同的组件间的比较,有三种策略

(1)同一类型的两个组件,按原策略(层级比较)继续比较VirtualDOM树即可。

(2)同一类型的两个组件,组件A变化为组件B时,可能VirtualDOM没有任何变化,如果知道这点(变换的过程中,VirtualDOM没有改变),可节省大量计算时间,所以用户可以通过shouldComponentUpdate()来判断是否需要判断计算。

(3)不同类型的组件,将一个(将被改变的)组件判断为dirtycomponent(脏组件),从而替换整个组件的所有节点。

注意:如上图所示,当组件D变为组件G时,即使这两个组件结构相似,一旦React判断D和G是不用类型的组件,就不会比较两者的结构,而是直接删除组件D,重新创建组件G及其子节点。虽然当两个组件是不同类型但结构相似时,进行diff算法分析会影响性能,但是毕竟不同类型的组件存在相似DOM树的情况在实际开发过程中很少出现,因此这种极端因素很难在实际开发过程中造成重大影响。

6、elementdiff

当节点处于同一层级时,diff提供三种节点操作:删除、插入、移动。

插入:组件C不在集合(A,B)中,需要插入

删除:

(1)组件D在集合(A,B,D)中,但D的节点已经更改,不能复用和更新,所以需要删除旧的D,再创建新的。

(2)组件D之前在集合(A,B,D)中,但集合变成新的集合(A,B)了,D就需要被删除。

移动:组件D已经在集合(A,B,C,D)里了,且集合更新时,D没有发生更新,只是位置改变,如新集合(A,D,B,C),D在第二个,无须像传统diff,让旧集合的第二个B和新集合的第二个D比较,并且删除第二个位置的B,再在第二个位置插入D,而是(对同一层级的同组子节点)添加唯一key进行区分,移动即可。

显示全部
相似文档