虚拟DOM详解

Posted WQTech

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了虚拟DOM详解相关的知识,希望对你有一定的参考价值。

虚拟DOM简介

  Virtual Dom可以看做一棵模拟了DOM树的javascript对象树,其主要是通过vnode,实现一个无状态的组件,当组件状态发生更新时,然后触发Virtual Dom数据的变化,然后通过Virtual Dom和真实DOM的比对,再对真实DOM更新。虚拟DOM其实就是一种模拟DOM的JavaScript数据结构。

  像SnabbDOM这种库的虚拟DOM是如下的数据结构:

  • sel 元素选择器 

  • data 元素属性 ●

  • children 元素子节点 ●

  • text 元素文本 ●

  • elm 对应dom元素 ●

  • key


SnabbDOM源码概述 

 说到SnabbDOM可能大家不太知道,但是大名鼎鼎的VUE就是使用SnabbDOM来提供虚拟DOM。SnabbDOM中的VNode结构如下:

虚拟DOM详解

  但是这里并没有直接提供对外接口,而是提供了h方法来创建VNode:

虚拟DOM详解  

  那么在具体使用场景如下:

虚拟DOM详解

  其中跟虚拟DOM各个周期中需要使用的hook方法都放在Hook.ts这个文件下:

虚拟DOM详解

  具体的钩子方法则是放在src/modules目录下的各个文件中。

  其中核心代码,包括整个Diff算法都放在snabbdom.ts文件中。


Diff算法

  SnabbDOM的diff算法主要有两个特点:

  • 同级比较

  • 就近复用

  虚拟DOM详解

  同级比较的意思是,对于两颗DOM树,只会比较同一层级的节点,如果节点类型不同直接干掉旧的节点,而不是继续比较。那么就近复用意味着如果节点类型相同就会对这个节点进行改造,而不是严格的比较各个属性书否相同。那么这里涉及snabbdom中的两个主要函数:


虚拟DOM详解

虚拟DOM详解

  其中diff的核心算法就在updateChildren中

虚拟DOM详解

虚拟DOM详解

  这个方法有些复杂,下面文字描述未必那么清晰,大家可以看我录制的视频——虚拟DOM详解。

  下图中白色图表代表目前实际的DOM节点,oldStart和oldEnd指向之前的虚拟DOM树,newStart和newEnd分别指向新的虚拟DOM节点。

虚拟DOM详解

  现在二者进行比较,首先处理头头、尾尾相同的节点,如果头尾尾头相同则同时移动新旧的指针

虚拟DOM详解

  接下来处理头尾尾头相同的节点,把newStartIdx和oldEndIdx相同的节点插入到oldStartIdx指向节点之前,newStartIdx向后移动,oldEndIdx向前移动;把newEndIdx和oldStartIdx相同的节点插入到oldEndIdx指向的节点之后,同时oldStartIdx向后移动,newEndIdx向前移动。

虚拟DOM详解

  处理完毕后的指针状态:

虚拟DOM详解

  接下来需要处理newStartIdx指向的节点11,那么这时候先去oldStartIdx和oldEndIdx的区间内寻找有没有这个节点,如果没有那么这个节点属于插入节点,这个节点会被插入到oldStartIdx指向的节点的前面,同时newStartIdx向后移动

虚拟DOM详解

  处理完11后,newStartIdx指向4,这个时候从oldStartIdx和oldEndIdx中能够找到这个节点,这说明它的位置被移动了,那么这时候只需要移动这个节点,把它移动到oldStartIdx所指向的节点之前,同时对就的虚拟DOM节点的位置进行标记,这里是设置为undefined。继续移动newStartIdx。

虚拟DOM详解

  接下来对7、 5、 6 都进行相同操作,这时候newStartIdx指向3的位置

虚拟DOM详解

  那么这个时候又变成了头头相同的情况,只需要同时将newStartIdx和oldStartIdx向后移动。虚拟DOM详解

  那么这时候newStartIdx越过了newEndIdx,到这里循环结束,这时候oldStartIdx和oldEndIdx中剩下的节点都是需要删除的节点。因为之前都已经打上了标记,所以这里只要节点8是需要删除的。当然也有时候会遇到oldStartIdx和oldEndIdx先相遇,这时候在newStartIdx和newEndIdx中的节点都是需要插入的。

  至此整个比较算法结束。


参考资料

深入 Vue2.x 的虚拟 DOM diff 原理

vue的Virtual Dom实现snabbdom解密

snabbdom

vue中Virtual DOM源码学习

 

下面是我录制的视频,有动画的可以更清晰的展示这个过程。

 




虚拟DOM详解

最后,来点个赞吧虚拟DOM详解


以上是关于虚拟DOM详解的主要内容,如果未能解决你的问题,请参考以下文章

虚拟DOM详解

虚拟DOM详解

前端 | 虚拟Dom详解 - (下篇)

虚拟DOM详解

Vue中diff算法详解

译React 优化:虚拟 DOM 详解