VUE源码学习第十二篇-patch(diff原理)

一、总述

    前面章节介绍了响应式的原理,当监听的属性值发生变化,会触发其相关的订阅watcher对象更新。如果在模板中使用了该属性,则会触发render wacher的更新,最终实现dom的更新。dom更新的有两种实现方式,一种是"全量"的全局更新,一种是"增量"的局部更新,很显然,后一种的效率会更高。VUE就是采用的一种,会先对新旧的vdom进行比较,形成patch,从而实现dom的局部更新。

  本章节主要介绍如何来比较vdom,即diff算法原理。

二、diff算法

vue是借鉴了react的diff算法,比较只会在同级间进行,不会跨级比较。下面这张图很形象的描述这种关系。

我们来看个dom实例

<!--变换前-->
<div><!--第一层级-->
  <div> <!--第二层级-->
       <p>vue</p><!--第三层级-->
       <input type="text"></input><!--第三层级-->
  </div>
  <span>diff</span><!--第二层级-->
</div>

<!--变换后-->
<div><!--第一层级-->
  <div> <!--第二层级-->
       <p>vue</p><!--第三层级-->
  </div>
  <span>diff</span><!--第二层级-->
  <input type="text"></input><!--第二层级-->
</div>

   最优的操作就是将第三层的input节点,直接移动到第二层,其他的节点保持不变。但在diff算法中,由于是同级比较,无法做到跨级移动,所以先比较第一层级元素(div),再比较第二层级(div,span),然后再比较第三层级(p,input),依次类推。具体的操作为,先在第二层增加input节点,然后在第三层删除该节点。

我们看下diff算法的原理,以下图为例,最终目标要将oldDom变换为newDom,以下是变换的方法。

1、在新老dom的首位和末位节点上,分别建立索引,如老dom的第一个节点索引标注为oldstart(简称os),最后一个节点oldend(简称oe),新节点也按此标注。

2、新老两组节点间相互比较,可以看到最多需要比较4次。即os->ns,os->ne,oe->ns,oe->ne。

3、4次比较后,会产生5种结果。

(1)os==ns,即旧dom的开始节点,与新dom的开始节点相等,保持os节点位置不变,os,ns的索引向后移动一位。

(2)os==ne,即旧dom的开始节点,与新dom的结束节点相等,将os节点移动到oe的索引位置后面,os索引向后移动一位,ne索引向前移动一位。

(3)oe==ns,即旧dom的结束节点,与新dom的开始节点相等,将oe节点移动os的索引位置前,oe索引向前移动一位,ns索引向后移动一位。

(4)oe==ne,即旧dom的结束节点,与新dom的结束节点相等,保持oe节点的位置不变,oe,ne的索引向前移动一位。

(5)两组节点互不相等,在os与oe间,查找是否有与ns相同的节点,如果有,则移动到os节点位置前;如果没有,则创建ns节点,并插入到os节点位置前。ns索引向后移动一位。

4、以下两种条件,满足其一就结束比较

(1)oe>os,表示olddom先遍历完,就创建ns,ne间的节点,插入到dom中的ne前。。

(2)ne>ns,表示newdom先遍历完,说明os,oe间的节点是多余的,直接删除。

以上的过程的描述比较晦涩,下面我们用一个实例,按照图解的方式为大家逐步分解。

三、实例说明

olddom最终变换后成为newdom

第一步:

添加索引,开始比较,os==ns,a节点的位置不变,同时,os,ns索引向后移动一位。

第二步:

os==ne,将b节点移动到oe索引的后面,同时,os索引向后移动一位,ne索引向前移动一位。

第三步:

oe==ne,f节点位置保持不变,同时,oe,ne索引向前移动一位。

第四步:

oe==ns,e节点移动到os索引位置前,同时,ns向后移动一位,oe向前移动一位。

第五步:

此时,两组节点互不相等,同时k节点与os->oe间节点元素不相同(d,c),创建k节点,并插入到os索引前。同时,ns索引向后移动一位。

第六步:

此时,ns与ne的索引位置是重合的,两组节点也是互不相等。g节点插入到ns的索引位置前,同时,ns索引向后移动一位。

第七步:

 

ne>ns,满足结束的条件,newdom先遍历完,os与oe之间的节点时多余,将移动掉。

最终由olddom变换成了newdom。

四、总结

本章节主要介绍diff算法的原理,下面将结合vue的源码,具体分析其实现过程。

发布了33 篇原创文章 · 获赞 95 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tcy83/article/details/92735848