patchVnode
Vnode
替换 oldVnode
el
Vnode
和 oldVnode
是否指向同一个对象,如果是,那么直接 return
el
的文本节点设置为 Vnode
的文本节点oldVnode
有子节点而 Vnode
没有,则删除 el
的子节点oldVnode
没有子节点而 Vnode
有,则将 Vnode
的子节点真实化之后添加到 el
updateChildren
函数比较子节点,这一步很重要child
和尾 child
oldS
、oldE
、S
、E
两两做 sameVnode
比较,有四种比较方式,当其中两个能匹配上那么真实 dom
中的相应节点会移到 Vnode 相应的位置,这句话有点绕,打个比方oldS
和 E
匹配上了,那么真实 dom
中的第一个节点会移到最后oldE
和 S
匹配上了,那么真实 dom
中的最后一个节点会移到最前,匹配上的两个指针向中间移动key
,那么会根据 oldChild
的 key
生成一张 hash
表,用 S
的 key
与 hash
表做匹配,匹配成功就判断 S
和匹配节点是否为 sameNode
,如果是,就在真实 dom
中将成功的节点移到最前面,否则,将 S
生成对应的节点插入到 dom
中对应的 oldS
位置,oldS
和 S
指针向中间移动。key
,则直接将 S
生成新的节点插入真实 DOM
(ps:这下可以解释为什么 v-for
的时候需要设置 key
了,如果没有 key
那么就只会做四种匹配,就算指针中间有可复用的节点都不能被复用了)key
的,且 key
为自身的值)
oldS
和 S
匹配,则将 dom
中的 a
节点放到第一个,已经是第一个了就不管了,此时 dom
的位置为:a b doldS
和 E
匹配,就将原本的 b
节点移动到最后,因为 E
是最后一个节点,他们位置要一致,这就是上面说的:当其中两个能匹配上那么真实 dom
中的相应节点会移到 Vnode 相应的位置,此时 dom 的位置为:a d boldE
和 E
匹配,位置不变此时 dom
的位置为:a d boldCh
先遍历完。就将剩余的 vCh
节点根据自己的的 index
插入到真实 dom
中去,此时 dom
位置为:a c d b
这个匹配过程的结束有两个条件:oldS > oldE
表示 oldCh
先遍历完,那么就将多余的 vCh
根据 index
添加到 dom
中去(如上图)S > E
表示 vCh
先遍历完,那么就在真实 dom
中将区间为[oldS, oldE]
的多余节点删掉