zoukankan      html  css  js  c++  java
  • DOM Diff(差分)算法

    1. 算法由来

    React调用render()方法后,会生成一个React元素组成的树。

    再次调用,生成一个新的树。React比较两者的差异,然后更新UI。

    如果单纯使用算法,来查找两个DOM树的差异值,算法复杂度为O(n^3)。

    为了提高渲染效率,假定:

    1)元素类型不同,是不同的树

    2)子元素可以通过key值来判断是否稳定

    这样算法复杂度降低到O(n)

    2. 算法比较步骤

    1. 比较根节点

    如果类型不同,卸载整个DOM节点,重新加载;

    如果类型相同

    1)如果是普通的html标签类型,比较属性,更新变化的属性。

    2)如果是组件类型,更新props,引发componentWillReceiveProps和componentDidUpdate方法调用

    2. 比较子节点(无key)

    如果类型不同,卸载字节点,重新加载;

    如果类型相同,依次比较字节点内容

    1)这种情况下,追加元素开销最小,因为前面都相同;

    2)头部插入元素开销最大;因为比较来看,第一个开始至最后一个都不相同。

    <ul>
      <li>Duke</li>
      <li>Villanova</li>
    </ul>
    
    <ul>
      <li>Connecticut</li>
      <li>Duke</li>
      <li>Villanova</li>
    </ul>

    3. 比较子节点(有key非index)

    对于上面的情况,如果同一列表的所有子元素有一个唯一值key值。

    React先比较key值,如果相同的key值存在,但是位置不同,只移动位置。

    元素移动位置只能在兄弟之间移动。

    <ul>
      <li key="2015">Duke</li>
      <li key="2016">Villanova</li>
    </ul>
    
    <ul>
      <li key="2014">Connecticut</li>
      <li key="2015">Duke</li>
      <li key="2016">Villanova</li>
    </ul>

    4. 比较子节点(有key是index)

    ˙这种情况,如果字节点顺序改变,可能会引起错误。

    比如子列表中含有非受控组件input。此时如果触发排序,会导致input的state出现互相篡改。

    示例

  • 相关阅读:
    Goahead源码解析(转)
    登录处理
    action交互
    无需FQ,自建本地CDN,秒上StackOverFlow!
    浅谈Linux中的信号处理机制(三)
    漫谈C++11 Thread库之原子操作
    漫谈c++11 Thread库之使写多线程程序
    浅谈Linux中的信号处理机制(二)
    浅谈Linux中的信号处理机制(一)
    CentOS7 安装Nginx
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11964693.html
Copyright © 2011-2022 走看看