React中的Diff算法浅析

74 阅读2分钟

React中哪里用到了diff算法

每次React中调用了render函数,就会形成一棵由React元素构成的树。在对state以及prop进行更新时,会形成一棵新的React树。React会比较新的树和旧的树,来判定如何高效进行UI更新。这一个比较的过程就用到了diff算法。

Diff算法执行过程

React 中的diff算法,首先会比较两棵树的根节点

  1. 如果节点类型不同,则会卸载前一棵树并且挂载新的树。
    例如:从<a>变成<div>

    卸载树的时候,对应的DOM节点也会被销毁。组件实例会执行componentWillUnmount()方法。当建立一颗新的树时,对应DOM节点会被创建以及插入DOM中。组件实例将执行UNSAFE_componentWillMount()方法,紧接着componentDidMount()方法。所有与之前的树相关联的state也会被销毁。



  1. 如果节点类型相同,React会只更新有改变的属性部分。例如


    // 改变前
    <div className="before"></div>
    
    // 改变后
    <div className="after"></div>
    

    处理完当前节点,继续对子节点进行递归操作。


  1. 对比同类型的组件元素

    当一个组件更新时,组件实例会保持不变,因此可以在不同的渲染时保持state一致。React将更新该组件实例的props以保证与最新的元素保持一致,并且调用该实例的 UNSAFE_componentWillReceiveProps()UNSAFE_componentWillUpdate()以及componentDidUpdate()方法。

为什么需要key

使用key是为了更高效的进行diff算法。


  1. 使用key前,当输入插入非最后一项时:


    <!-- 元素插入前 -->
    <ul>
        <li>second</li>
    <ul>
    <!-- 更新后 -->
    <ul>
        <li>first</li>
        <li>second</li>
    </ul>
    

    diff算法不会保留,<li>second</li>这一相同元素,而是会将所有的<li>进行更新。

  2. 使用key后,React会使用key来匹配原来树上所有的子元素,增加了转换效率。

key的注意事项

  1. 应该具有稳定可预测以及列表唯一性的特质。

  2. 使用不稳定的key例如Math.random(),会导致组件实例和DOM被不必要的创建,导致性能的下降。

  3. 最好不要用下标来定义key,当列表有顺序的改变,会降低diff算法的速度。

参考文章:# 协调