React diff算法

React diff算法

看到后觉得加深了理解:组件只不过是一段Html结构的包装容器,并且具备管理这段Html结构的状态等能力。

React 源码剖析系列 - 不可思议的 react diff

React diff 是Virtual DOM 的加速器,具体问题就是计算一棵树形结构转换成另一棵树形结构的最少操作。

三个策略:

  • 基于三个策略:
  1. Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。(tree diff)

    一种忽略跨层的先设前提,牺牲一些开发自由度来获取算法的高效性。

    **开发建议:**保持稳定的 DOM 结构会有助于性能的提升。

  2. 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结(component diff)

    不同类直接构建重建,这里是基于我们开发时组件封装组件之间的差异性较大而提出来的。

    **开发建议:**封装组件的时候要思考,为什么要封装它,它很独特吗,要是它有相似的兄弟呢,有的话为什么不尝试下合并呢

  3. 同父类组件:对于同一层级的一组子节点,它们可以通过唯一 id 进行区分。(element diff)

    这让我联想到了,实际开发时渲染react数组数据的时候增加key属性。

    **开发建议:**在开发过程中,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。

对这三个策略理解的不是很好,然后看到一张图:

preview

这是react状态改变之后对应不同的组件类型进行的一个节点更新,其中有三种:文本、Dom、组件;

这里文本直接比较即可,组件则交由component(shouldComponentUpdate方法+策略一)去管理更新,重点是基本元素Dom

  • 更新属性,对比出前后属性的不同,局部更新。并且处理特殊属性,比如事件绑定。
  • **(重点:算法实现处)**子节点的更新,子节点更新主要是找出差异对象,找差异对象的时候也会使用上面的shouldUpdateReactComponent来判断,如果是可以直接更新的就会递归调用子节点的更新,这样也会递归查找差异对象。不可直接更新的删除之前的对象或添加新的对象。之后根据差异对象操作dom元素(位置变动,删除,添加等)。

算法:

preview

插入,移动,删除:

img

流程:

设置一个lastIndex属性两个数组最远遍历到哪里了

lastIndex=0

  1. B(0):通过key发现旧的有B(1),lastIndex=1
  2. A(1):通过key发现旧的有A(0),lastIndex不变,但是0<1,需要移动A节点到1(当前)处,此时B就被动调整到了0的位置。
  3. D(2):通过key发现旧的有D(3),lastIndex=3
  4. C(3):通过key发现旧的有C(2),lastIndex不变,但是2<3,需要移动C节点到3(当前)处,此时D就被动调整到了2的位置。

再来一道:

img

  1. B(0):旧的B(1),lastIndex=1

  2. E(1):旧数组中不存在!此时增加E至数组(当前位置1)

  3. C(2):旧的C(2),lastIndex=2

  4. 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值