对react中虚拟dom和diff算法的理解

虚拟dom的出现

直接使用dom进行操作时排版与重绘的效率低,速度慢。例如插入一个dom元素,元素本身或者继承很多属性,还需要注册很多方法,导致一个创建一个简单的dom也要消耗很多时间。虚拟dom是在首次渲染dom时,多了一层虚拟dom的计算,在dom的基础上建立了一个抽象层。当有改动时,会生成一个新的虚拟dom与上一次生成的虚拟dom去diff,得到一个差异化的部分patch,最后将patch打到浏览器的dom上去。

虚拟dom实现:diff算法

两个树的完全的diff算法是一个时间复杂度为 O(n3) 的问题。 但是在前端中,你会很少跨层地移动DOM元素,所以真实的DOM算法会对同一个层级的元素进行对比。div只会和同一层级的div对比,第二层级的只会和第二层级对比。 这样算法复杂度就可以达到O(n)。
三个策略

1. tree diff 层级
DOM节点跨层级的移动操作特别少,可以忽略不计
对数进行分层比较,两棵树只会对同一层次的节点进行比较
对react中虚拟dom和diff算法的理解_第1张图片
如果出现了 DOM 节点跨层级的移动操作,也只会对应层级进行删除和创建。不会有移动的操作,因此尽量不用进行dom节点跨层级操作

2. component diff 组件级
拥有相同类的两个组件会生成相似的树形结构,不同类的两个组件会生成不同的树形结构
进行了tree diff之后 如果有需要更新的组件,则进行component diff对比组件的差异。
对比后,组件类型相同,则此组件不需要更新,又进行element diff进行元素级别的对比。
对比后,组件类型不同,需要移除旧组件,创建新组件
3. element diff 元素级
对于同一层级的一组子节点,可以通过唯一key区分
比较后,对于新节点插入,对于多余的节点删除,对于换位的节点进行移动。key值的作用是,只要判断key值对应的元素没有改变,只需要执行移动。

流程:新旧节点遍历后,新节点newindex,旧节点oldindex。如果发现新集合中某节点在旧集合中也存在,于是对比两个index,newindex大于oldindex,需要将旧节点移动到新的位置,相反则不动,找不到对应的节点,新增,最后旧节点在新节点用不上旧删除。最后一个节点移动到第一个位置,对导致n-1个节点都进行后移,影响性能,尽量避免。
不能用 index 作为 key,当数组中的数据发生变化时: React 比较更新前后的元素 key 值,如果相同则更新。如果不同则销毁之前的,重新创建一个元素。当以数组的下标index作为key值时,其中一个元素发生了变化 就有可能导致所有元素的key值发生改变 。

你可能感兴趣的:(react,dom)