React学习-- React源码(5)diff算法

diff作为VirtualDOM的加速器,其算法上的改进优化是React整个界面渲染的基础和性能的保障。

diff会帮助我们就散出VirtualDOM中真正变化的部分,并只针对该部分进行原生DOM操作,而不是渲染整个页面。从而保证了每次操作更新后页面的高效渲染。

传统的diff算法

计算一颗树形结构转换成另一颗树形结构的最少操作,是一个很复杂的问题。传统diff算法通过循环递归对节点进行依次对比,效率低下。复杂度可达到O(n^3)。

React改进了diff算法,新的diff算法更加稳定、高效。

React diff算法详解

React将VirtualDOM树转换为actualDOM的最少操作过程称为调和(reconciliation)。

diff算法就是调和过程的具体实现。

1、diff策略

策略1: DOM节点跨层级的移动操作很少,忽略不计。
策略2: 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。
策略3: 对于同一个层级的一组子节点,可以通过它们唯一的ID来区分。

2、tree diff

基于策略1,React对树的算法进行了简洁明了的优化:只对树进行分层比较,两棵树只会对同一层次的节点进行比较。

React只会对相同层级的DOM节点进行比较,即同一个父节点下的所有子节点,当发现该节点已经不存在了,就会删除该节点和其所有子节点,不会再做进一步的比较。

而如果真的出现了跨层级的移动,并不会出现移动操作,而是被移动的跟节点被删除而后重新创建。

3、component diff

组件之间的比较策略:
1、如果是同一类型的组件,按原策略继续比较VirtualDOM树即可
2、如果不是,则将该组件判断为dirty component,从而替换整个组件下的所有子节点。
3、对于同一类型的组件,可能其virtualDOM没有任何变化,如果能确切的知道这一点,那么就可以节省大量的diff运算时间。因此,React允许用户通过shouldComponentUpdate()来判断是否需要对组件进行diff算法分析。

4、element diff

当节点处于同一个层级的时候,diff提供了三种节点操作:INSERT_MARKUP(插入)、MOVE_EXISTING(移动)、REMOVE_NODE(删除)。 1、插入:新的组件不在旧的集合里,也就是是一个全新的节点。 2、旧集合中有新的组件类型,且element是可更新的类型,generateComponent-Children已经调用receiveComponent,这种情况下prevChild=nextChild,就需要做移动操作,可以复用以前的DOM节点。 3、旧组件类型,在新集合里也有,但对应的element不同则不能直接复用和更新,需要执行删除操作。或者旧组件不在新集合里,也要执行删除操作。

相关文章

导入moment 使用方式 年月日,时分秒 星期几 相对时间 7天后 2小时后 明天 将毫秒转换成年月日
@ 一、前言 为什么介绍redux-actions呢? 第一次见到主要是接手公司原有的项目,发现有之前的大佬在处理...
十大React Hook库 原文地址:https://dev.to/bornfightcompany/top-10-react-hook-libraries-4065 原文...
React生命周期 React的生命周期从广义上分为挂载、渲染、卸载三个阶段,在React的整个生命周期中提供很...
React虚拟DOM的理解 Virtual DOM是一棵以JavaScript对象作为基础的树,每一个节点可以将其称为VNode,用...
React中JSX的理解 JSX是快速生成react元素的一种语法,实际是React.createElement(component, props, ....