开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
前言
在了解diff算法之前,我们需要掌握的是虚拟节点,也就是我们常说的Vitriol Dom是什么、是如何形成的
Vitriol Dom
以下我将从两方面:Vitriol Dom是什么,以及为什么要使用Vitriol Dom(下文简称VNode,虚拟节点)为大家说明。
What
相比真实DOM,即我们常用的html标签,VDOM是真实DOM的js对象,他通常使用对象的形式将一例子的DOM包裹起来,举个例子,常见的形式如下:
{
"sel": "div",//每个VNode必须要有sel属性
"data": {},
"children": [
{"sel": "div","text": "666",},
{"sel": "div","text": "777",}
]
}
而许多的虚拟节点组合在一起就是一个虚拟DOM树。
Why
那么肯定有人会问,我们已经有真实的DOM元素了,为什么还要弄一个虚拟元素呢?——答案非常简单,还记得我之前提到过的节流和重载吗,为了减少浏览器的负担,我们可以使用这种方法比对每一次编译时页面的不同,从而只需要修改VDOM即可使最小化更新视图。而使用虚拟节点更新视图,我们必须依赖一个h函数。
h函数
h函数,可以将它理解为一个渲染函数。在真正转变成Dom节点之前,其实我们会经过两个步骤:先将标签中的节点编译成VNode,然后多个VNode组合起来转化为VDom,最终再被渲染成真实DOM。而h函数,又被称作createNode函数,主要用于创建虚拟节点VNode。
如何实现创建虚拟VNode?——递归调用h函数,由h函数return VNode返回一个虚拟节点对象。
VDOM和VNode
那么到这里有人又会问了,一会儿VNode一会儿VDOM,他俩究竟有什么区别呢?——Vue在生成真实的DOM之前,会先将节点转换成VNode,而VNode组合在一起形成一颗树结构,就是VDOM。
简而言之:VNode(大树),VDOM(森林)
graph TD
VNode1号 --> VDOM
VNode2号--> VDOM
VNode3号--> VDOM
... --> VDOM
那么,在实现寻找差异之前,我们不得不写出一个可以找到两个视图之间差异的方法,也就是本节的重头戏——diff算法。
diff算法
首先我们来简述一下这个算法。这个算法的主要实现思路是怎么样的呢?——双指针实现差异查找。为了更好地演示diff算法的过程,下图模拟了一个例子的实现过程
主要实现过程为:
当star指针不超过end指针时,让old中的star和end与new中的star和end作比较
Star://进入程序
while(star指针不超过end指针时){//让old中的star和end与new中的star和end作比较
|——``若有相同的元素则以新虚拟DOM的位置为准生成真实DOM节点(即图中白色节点处)``
|——``若未发现相同,则旧虚拟DOM的star指针右移,新虚拟DOM的end指针左移,然后重复上一步。``
}
|——``最后比对真实DOM和新虚拟DOM,若有新虚拟DOM中有多余的元素,则直接像图解中最后一步一样加入到真实DOM中即可``