React 虚拟 Dom 和 diff 算法

React将DOM抽象为虚拟DOM, 而后经过新旧虚拟DOM 这两个对象的差别(Diff算法),最终只把变化的部分从新渲染,提升渲染效率的过程; (概念讲完再描述一遍)javascript

JS对象2Html.png

JS对象2HTML完整版.png

虚拟DOM的算法步骤.png

一句话: 用 JS 对象的形式,来表现一棵真是的 DOM 树;java


Diff 算法

    • 当你实际开发使用React的时候,在某个时间点 render() 函数建立了一棵React元素树,也就模拟一个虚拟 DOM 树,
    • 在下一个state或者props更新的时候,render() 函数将建立一棵新的React元素树, 也就模拟了一个新的虚拟 DOM 树,
    • 既然模拟出了新旧两棵DOM 树, 那么如何高效的进行新旧两棵树的对比呢??
    • 固然是使用 DIff 算法...
  1. 传统的 Diff 算法也是一直都有的;算法

    • 可是它的时间复杂度为O(n^3) 意思是: 在React中更新10个元素则须要进行1000次的比较。(1000个===10亿)
  2. React 经过制定大胆的策略,将 O(n^3) 复杂度的问题转换成 O(n^1=n) 复杂度的问题。bash

      1. 两个不一样类型的元素会产生不一样的树
      1. 对于同一层级的一组子节点,它们能够经过惟一 key 进行区分
    • 基于以上两个前提策略,React 分别对 tree diff、component diff 以及 element diff 三种 diff 方法是 进行算法优化,
    • 下面介绍优化后的几种算法

Tree Diff

概念: 将新旧两颗虚拟 DOM 树,按照层级对应的关系,从头至尾的遍历一遍,,就能找到那些元素是须要更新的,这种方式: Tree Diff函数

Tree Diff 01.png

1 只会对相同颜色方框内(同级)的DOM节点进行比较,即同一父节点下的全部子节点
2 当发现节点已经不存在,则该节点及其子节点会被彻底删除掉,不会用于进一步的比较
复制代码

Tree Diff 02.png

  • 执行过程:create A -> create B -> create C -> delete A

Component Diff

不一样组件之间的对比 概念: 在对比每个层级的时候,会有本身的组件,这种组件的对比方式就叫: Component Diff ;性能

​ 这种对比方法其实比较的就是类型.↓↓↓优化

  • 若是类型相同,暂时不更新,spa

  • 若是类型不相同,就须要更新; ( 删除旧的组件,再建立一个新的组件,插入到删除组件的那个位置)code

Component Diff 01.png

  • 执行过程:delete D -> create G

Element Diff

同一层级中元素之间的对比
概念: 在类型相同的组件内, 再继续对比组件内部的元素,查看内部元素是否相同,若是须要修改,找到须要修改的元素,进行针对性的修改! 这种方式就叫: Element Diffcomponent

三种节点操做:
1 INSERT_MARKUP(插入)
2 MOVE_EXISTING(移动)
3 REMOVE_NODE(删除)

INSERT_MARKUP:新的 component 类型不在老集合里,须要对新节点执行插入操做。

MOVE_EXISTING:老的集合包含新的 component 类型,就须要作移动操做,能够复用之前的 DOM 节点。

REMOVE_NODE:老的 component 不在新集合里的,须要执行删除操做 或者 老的 component 类型在新集合里也有,但对应的 element 不一样则不能直接复用和更新,须要执行删除操做
复制代码

Element Diff 01.png

  • 执行过程:B != A,则建立并插入 B,删除 A;以此类推,建立并插入 A、D、C,删除 B、C、D

    Element Diff 02.png

  • 执行过程:B、D 不作任何操做,A、C 进行移动操做


diff 算法总结:

  1. 保持完整的结构,有利于性能的提高

  2. 尽可能使用相同类型的组件

  3. 在进行 Element 或Component 级别对比的时候,为了提升对比的效率, React 推荐咱们为每一个 for 循环建立出来的元素或者组件,提供一个惟一的 key;

  4. Tree diff :将新旧两棵 DOM 树,按照层级对应的关系,这样只须要对树进行一次遍历,就可以找到哪些元素是须要更新的;

  5. Component Diff: 在对比每一层的时候,每一层都有本身的组件, 那么组件之间的对比,叫作 Component diff , 对比的方式,就是查看两个组件的类型是否相同,若是相同,则暂时认为不须要更新,若是类型不一样,则表示更新(先把旧的组件删除,再建立一个新的组件,插入到刚才删除的位置);

  6. Element Diff:若是新旧 DOM 树中的组件类型相同,会继续比较这两个组件内部的元素是否也相同,若是元素发生了改变,则找到须要修改的元素,有针对性的修改,这种组件内部元素级别的对比叫: Element Diff;

相关文章
相关标签/搜索