React diff 算法

  React是web前端UI库,关注的是如何高效地根据数据渲染UI界面。virtual dom 与高效的diff算法的结合,使得当数据发生变动时,react 能经过简洁高效的算法找出dom中真正变动,同时根据变动进行dom操做渲染UI界面。前端

  传统的根据一个树形结构到另一个树形结构的装换操做是一个复杂且耗时的过程,通常时间复杂度会达到O(n^3),加上每一个dom节点都是一个附带大量信息的对象,通常的算法可能作到实时根据数据变动,更新UI视图。react

  React根据dom树的特定场景,制定了大量且高效的diff策略:web

  1. Web UI中dom节点的跨层次的移动操做不多,可忽略算法

  2. 拥有相同类型的组件有类似的树形结构,不一样类型的节点的树形结构大几率不相同dom

  3. 对于同一层次的节点,能够经过惟一的id进行区分性能

  根据上面的3点策略,两颗dom数的比较,只会对同一层次的几点进行比对。优化

  <1>当出现跨层次移动是,只有建立和删除操做,是一种影响React 性能的操做,React 建议不要进行dom跨层次的操做,开发组件时,保持稳定的dom结构会有助于性能的提高,能够经过CSS隐藏或显示节点,而不是真的移除或添加节点。spa

  <2>若是是同一类型的组件,则按照继续比较下一层的节点,若是不是同一类型的组件,则判断为dirty Component,从而根据新组件替换整个组件下的全部子组件,对于同一类型的组件,可能数据没有发生变动或者UI视图不须要根据,React 容许开发者经过shouldComponentUpdate(nextProps,nextState)来判断该组件是否须要进行diffcode

  <3>对于同一层次下的子组件,react 建议添加key来惟一的区分,以提升diff的效率。首先会对的新的节点进行遍历操做,经过惟一的key能够找出须要新建、删除、以及移位的节点。若是老集合中存在相同的节点则进行移位操做,避免的节点的新建删除开销(包括计算及dom操做)。移位操做算法以下:对象

  

let lastIndex = 0  // 记录当前元素以前的元素在oldList中最靠后的位置 

  for(element in newList){     // element._mountIndex 是当前元素在老List的位置,newIndex 是当前元素在新 
         // LIst中的位置

       if(element._mountIndex < lastIndex)       move(element, newIndex)     lastIndex = Math.max(element._mountIndex, lastIndex)   }

     策略是若是当前元素在老List中的位置,小于在它以前元素在老List的中的位置,就说明当前元素须要向后移动才能变成新的List.

  总结:diff算法并非要构造一个新的树,而比对找出变化的部分,来对老的dom树进行最少的操做,从而优化UI更新的效率。

     

    参考:https://zhuanlan.zhihu.com/p/20346379

相关文章
相关标签/搜索