Vue3之Diff算法源码分析

// 1. sync from start

// (a b) c

// (a b) d e

while (i <= e1 && i <= e2) {

const n1 = c1[i]

const n2 = (c2[i] = optimized

? cloneIfMounted(c2[i] as VNode)
normalizeVNode(c2[i]))

if (isSameVNodeType(n1, n2)) {

patch(

n1,

n2,

container,

null,

parentComponent,

parentSuspense,

isSVG,

slotScopeIds,

optimized

)

} else {

break

}

i++

}

// 2. sync from end

// a (b c)

// d e (b c)

while (i <= e1 && i <= e2) {

const n1 = c1[e1]

const n2 = (c2[e2] = optimized

? cloneIfMounted(c2[e2] as VNode)
normalizeVNode(c2[e2]))

if (isSameVNodeType(n1, n2)) {

patch(

n1,

n2,

container,

null,

parentComponent,

parentSuspense,

isSVG,

slotScopeIds,

optimized

)

} else {

break

}

e1–

e2–

}

// 3. common sequence + mount

// (a b)

// (a b) c

// i = 2, e1 = 1, e2 = 2

// (a b)

// c (a b)

// i = 0, e1 = -1, e2 = 0

if (i > e1) {

if (i <= e2) {

const nextPos = e2 + 1

const anchor = nextPos < l2 ? (c2[nextPos] as VNode).el : parentAnchor

while (i <= e2) {

patch(

null,

(c2[i] = optimized

? cloneIfMounted(c2[i] as VNode)
normalizeVNode(c2[i])),

container,

anchor,

parentComponent,

parentSuspense,

isSVG,

slotScopeIds,

optimized

)

i++

}

}

}

// 4. common sequence + unmount

// (a b) c

// (a b)

// i = 2, e1 = 2, e2 = 1

// a (b c)

// (b c)

// i = 0, e1 = 0, e2 = -1

else if (i > e2) {

while (i <= e1) {

unmount(c1[i], parentComponent, parentSuspense, true)

i++

}

}

// 5. unknown sequence

// [i … e1 + 1]: a b [c d e] f g

// [i … e2 + 1]: a b [e d c h] f g

// i = 2, e1 = 4, e2 = 5

else {

const s1 = i // prev starting index

const s2 = i // next starting index

// 5.1 build key:index map for newChildren

const keyToNewIndexMap: Map<string | number | symbol, number> = new Map()

for (i = s2; i <= e2; i++) {

const nextChild = (c2[i] = optimized

? cloneIfMounted(c2[i] as VNode)
normalizeVNode(c2[i]))

if (nextChild.key != null) {

if (DEV && keyToNewIndexMap.has(nextChild.key)) {

warn(

Duplicate keys found during update:,

JSON.stringify(nextChild.key),

Make sure keys are unique.

)

}

keyToNewIndexMap.set(nextChild.key, i)

}

}

// 5.2 loop through old children left to be patched and try to patch

// matching nodes & remove nodes that are no longer present

let j

let patched = 0

const toBePatched = e2 - s2 + 1

let moved = false

// used to track whether any node has moved

let maxNewIndexSoFar = 0

// works as Map<newIndex, oldIndex>

// Note that oldIndex is offset by +1

// and oldIndex = 0 is a special value indicating the new node has

// no corresponding old node.

// used for determining longest stable subsequence

const newIndexToOldIndexMap = new Array(toBePatched)

for (i = 0; i < toBePatched; i++) newIndexToOldIndexMap[i] = 0

for (i = s1; i <= e1; i++) {

const prevChild = c1[i]

if (patched >= toBePatched) {

// all new children have been patched so this can only be a removal

unmount(prevChild, parentComponent, parentSuspense, true)

continue

}

let newIndex

if (prevChild.key != null) {

newIndex = keyToNewIndexMap.get(prevChild.key)

} else {

// key-less node, try to locate a key-less node of the same type

for (j = s2; j <= e2; j++) {

if (

newIndexToOldIndexMap[j - s2] === 0 &&

isSameVNodeType(prevChild, c2[j] as VNode)

) {

newIndex = j

break

}

}

}

if (newIndex === undefined) {

unmount(prevChild, parentComponent, parentSuspense, true)

} else {

newIndexToOldIndexMap[newIndex - s2] = i + 1

if (newIndex >= maxNewIndexSoFar) {

maxNewIndexSoFar = newIndex

} else {

moved = true

}

patch(

prevChild,

c2[newIndex] as VNode,

container,

null,

parentComponent,

parentSuspense,

isSVG,

slotScopeIds,

optimized

)

patched++

}

}

// 5.3 move and mount

// generate longest stable subsequence only when nodes have moved

const increasingNewIndexSequence = moved

? getSequence(newIndexToOldIndexMap)
EMPTY_ARR

j = increasingNewIndexSequence.length - 1

// looping backwards so that we can use last patched node as anchor

for (i = toBePatched - 1; i >= 0; i–) {

const nextIndex = s2 + i

const nextChild = c2[nextIndex] as VNode

const anchor =

nextIndex + 1 < l2 ? (c2[nextIndex + 1] as VNode).el : parentAnchor

if (newIndexToOldIndexMap[i] === 0) {

// mount new

patch(

null,

nextChild,

container,

anchor,

parentComponent,

parentSuspense,

isSVG,

slotScopeIds,

optimized

)

} else if (moved) {

// move if:

// There is no stable subsequence (e.g. a reverse)

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-DKiaa76x-1715663886668)]

[外链图片转存中…(img-0gaUMTmQ-1715663886668)]

[外链图片转存中…(img-pykXvcdF-1715663886668)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值