浅谈React虚拟DOM Diff算法

为什么要使用虚拟DOM

因为浏览器的DOM渲染是非常消耗性能的,很低效,我们使用虚拟DOM是为了提高DOM的渲染性能;

什么是虚拟DOM

虚拟DOM就是把真实的DOM树通过createElement转换成js中的一个对象树,在内
存中作比较

在虚拟DOM中是如何渲染页面的

虚拟DOM一旦创建以后,就会根据组件内部的状态,父组件props传过来的修改,以及一些全局状态的更新,就会导致当前
组件产生一个新的js对象树,然后就会在内存中通过一个diff比较算法来比较当前的虚拟DOM节点和之前的虚拟DOM节点,将比较
的结果在DOM树上重新渲染

Diff算法(逐层比较)

Diff算法也叫同级比较算法,是逐层比较的,一旦发现某个节点没了,就删除,发现新增了一个节点,那就新增一个节点,发现
该位置该存在,就原地保留该节点。但是标准的Diff算法复杂度需要O的三次方,这样的算法显示是无法满足性能要求的,所以
势必要对该算法进行简化的。这看上去非常有难度,然而Facebook工程师却做到了,他们结合Web界面的特点做出了两个简单的
假设,使得Diff算法复杂度直接降低到O(n)复杂度从O的三次方变为了O的一次方;同时也解决了两个问题:如果两棵树比较变化
特别大,就完蛋了,如果兄弟节点进行排序和插入新节点,那还是完蛋,你要全删了再一个一个加;

接下来就要说这两个假设

(1)两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构;
(2)对于同一层次的一组子节点,它们可以通过唯一的id进行区分。

关于第一个假设

-其实看起来并不奇怪,在我们的react中,由于组件化的思想,相同组件中本就是类似的DOM解构,只有不同的组件才会产生不
同的DOM结构,根据React官方博客,这一假设至今为止没有导致严重的性能问题。
-这当然也给我们一个提示,在实现自己的组件时,保持稳定的DOM结构会有助于性能的提升。例如,我们有时候可以通过CSS隐
藏或显示某些节点,而不是真正的去移除或添加DOM节点;

关于第二个假设,也就是我们为什么循环的时候会加上一个key值的解释

-你想,我们兄弟节点如果进行排序的时候,每个位置的节点都变了,那我们就要把每个位置的节点都重新删除掉,然后再一个
一个的重新添加上去,这样的话更新过程会特别的低效,所以第二个假设的作用就是让我们开发者在开发过程中给每个节点加上
一个:key值,也就是给每个节点加上一个唯一标识,这样就会根据列表节点提供唯一的key属性可以帮助React定位到正确的节点
进行比较,从而大幅减少DOM操作次数,提高了性能。

还有一个就是我们给节点加标识的时候,尽量不要使用下标index

-如果你用下标,你要插入一个节点,那下标不就全乱了,但是我们也可以:key="“index”",将下标转换成字符串就行,但是我
们不提倡使用index作为key的,因为我们会用用数据库返回来的id作为key值。

猜你喜欢

转载自blog.csdn.net/qq_40752643/article/details/84099701