react 学习笔记——diff算法

diff算法是react中经典之作,他很巧妙,该算法是react整个界面渲染的基础和保障。

将之前先介绍一下传统的DIff的弊端:传统的Diff算法通过循环递归依次对节点进行对比,效率比较低下,算法的时间复杂度为O(n^3),n为树的节点数,当节点比较多的时候,这种搜索次数将会急剧增加,计算机的负荷开销将会十分巨大。


DIFF的三种策略:DOM间的diff、组件间的diff、元素间的diff

1. tree diff(这种情况比较少)

react对树的算法进行了简单的优化:对树进行分层的比较,两棵树只会对同层的节点进行比较。

react通过updateDepth对Virtual DOM树进行层级的控制,只会对相同层级的DOM节点进行比较,即同一个父节点下的所有的子节点。当发现节点已经不存在的时候,则该节点即子节点会被完全的删除,不会进行进一步的比较了,这样只需要对树遍历一次即可。

(注意:开发组件的时候,保持组件的DOM结构的稳定有助于提高性能,例如:可以通过CSS来隐藏节点,而不是真正的删除或者增加DOM节点)

2.component diff

组件间的比较算法:

·如果是相同类型的组件,按照tree diff的策略进行比较;

·如果不是,将该组件判断为dirty component,然后将该节点下面的所有的子节点全部替换掉;

·对于相同类型的组件,可能他的Virtual DOM没有任何的变化,如果知道这一点,将极大的节省计算diff的时间,因此,react允许用户通过shouldComponentUpdate()来判断该组件是否需要diff算法。


以上两个都是比较简单的情况:

3.element diff

当节点在同一层级的时候,diff提供三种操作:INSERT_MAPKUP(插入)、MOVE_EXISTING(移动)、REMOVE_NODE(删除)。

此处引进key值:这是由于,当层级中的节点元素没有发生变化的时候,而是仅仅是位置的变化,如果按照上述的原则位置不同将会重新绘画,这将影响渲染的性能,因此,为每个节点添加唯一的key值,当发现有相同的节点的时候,不需要进行重新的创建或删除节点的操作。


如图所示:diff的操作的过程(就是旧节点更新为新节点的过程)

首先对新节点逐一进行遍历,通过唯一的key值来判断旧的集合中是否存在相同的节点,图中,先遍历新图中的节点,首先取到节点B,发现B节点在旧图中存在(B在旧图中的index=1),此时比较lastIndex(访问过的节点的最右的位置,初始值为0)与B在旧图中的index比较,if(index<lastIndex),则进行移动操作,此时,index=1>lastIndex=0,因此B节点不移动,接下来更新lastIndex的值:lastIndex= max(lastIndex,index),此时lastIndex值更新为1;

接着取新节点A,A在旧节点中的位置index=0,此时,lastIndex= 1,满足(index<lastIndex)的条件,因此,将A的值更新为新节点中的位置,此时lastIndex仍然为1;

接下来取到新节点的D,D在旧节点中的位置为index=3,此时lastIndex=1,不满足(index<lastIndex)条件,因此,D的位置不更新,此时lastIndex = max(lastIndex,index) = 3;

最后取到节点C,C在旧节点的位置为index= 2,此时lastIndex=3,满足(index<lastIndex)条件,所以对,C节点进行移动操作。


上述仅仅是,一种情况,如果出现遍历一遍新节点过程中,在旧节点中不存在该节点,应该添加该节点,最后遍历完新节点后,还要遍历一遍 旧节点,将旧节点中多余的节点删除掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值