1. 程式人生 > >vue diff演算法 patch

vue diff演算法 patch

1、diff比較演算法

圖示:
在這裡插入圖片描述
diff比較只會在同層級進行, 不會跨層級比較。

程式碼示例

<!-- 之前 -->
<div>           <!-- 層級1 -->
  <p>            <!-- 層級2 -->
    <b> aoy </b>   <!-- 層級3 -->   
    <span>diff</Span>
  </P> 
</div>

<!-- 之後 -->
<div>
<!-- 層級1 --> <p> <!-- 層級2 --> <b> aoy </b> <!-- 層級3 --> </p> <span>diff</Span> </div>

我們可能期望將<span>直接移動到<p>的後邊,這是最優的操作。

但是實際的diff操作是:

(1)<p>移除裡的<span>

(2)建立一個新的<span>

插到<p>的後邊。

因為新加的<span>在層級2,舊的在層級3,屬於不同層級的比較。

vue原始碼中會有一個sameVnode方法:

function sameVnode (a, b) {
  return (
    a.key === b.key && (
      (
        a.tag === b.tag &&
        a.isComment === b.isComment &&
        isDef(a.data) === isDef(b.data) &&
        sameInputType
(a, b) ) || ( isTrue(a.isAsyncPlaceholder) && a.asyncFactory === b.asyncFactory && isUndef(b.asyncFactory.error) ) ) ) }

表示2個Vnode是否是同一個節點:

(1)當是一樣的節點,直接複用(若設定key的話)。

(2)當不是一樣的節點的話,新節點直接替換老節點。

2、比較原則

圖示:
在這裡插入圖片描述
圖師說明:

粉紅色的部分為oldNode,黃色的表示newNode。

在這裡插入圖片描述
s和e指標指向它們的頭child和尾child Node的指標。

現在分別對oldS、oldE、S、E兩兩做sameVnode比較,有四種比較方式。

即:

oldS == S?

oldS == E?

oldE == S?

oldE == E?

diff演算法:

如果是oldS和E匹配上了,那麼真實dom中的第一個節點會移到最後
如果是oldE和S匹配上了,那麼真實dom中的最後一個節點會移到最前,匹配上的兩個指標向中間移動
如果四種匹配沒有一對是成功的,那麼遍歷oldChild,S挨個和他們匹配,匹配成功就在真實dom中將成功的節點移到最前面,如果依舊沒有成功的,那麼將S對應的節點插入到dom中對應的oldS位置,oldS和S指標向中間移動。

3、key

不設key,newCh和oldCh只會進行頭尾兩端的相互比較。

設key後,除了頭尾兩端的比較外,還會從用key生成的物件oldKeyToIdx中查詢匹配的節點,所以為節點設定key可以更高效的利用dom。

(1)下圖是沒有設定key的diff演算法
在這裡插入圖片描述
(2)下圖是有設定key的diff演算法
在這裡插入圖片描述
參考文章:

https://www.cnblogs.com/wind-lanyan/p/9061684.html

https://segmentfault.com/a/1190000008782928?utm_source=tag-newest