vue3 Diff算法
patch
函数的外围就是Diff算法。
function patch (oldVnode, vnode, parentElm) { if (!oldVnode) { addVnodes(parentElm, null, vnode, 0, vnode.length - 1); } else if (!vnode) { removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1); } else { if (sameVnode(oldVNode, vnode)) { patchVnode(oldVNode, vnode); } else { removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1); addVnodes(parentElm, null, vnode, 0, vnode.length - 1); } }}
patch
函数的性能次要是新旧VNode
节点,将差别更新到视图上,所以传入参数有新旧2个VNode
以及父节点element
,先捋清函数的主逻辑:
首先当旧节点oldVnode
不存在时,相当于新节点vnode
代替没有的节点,所以间接用addVnodes
将这些节点批量增加到parentElm
下面。
if (!oldVnode) { addVnodes(parentElm, null, vnode, 0, vnode.length - 1);}
同理,当新VNode节点vnode
不存在时,相当于把旧的节点删除,所以间接应用removeVnodes
函数进行批量的节点删除。
else if (!vnode) { removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1);}
最初一种状况,就是当旧节点oldVnode
和新节点vnode
同时存在的状况下,须要判断它们是否属于sameVnode
(雷同的节点)。如果是则执行patchVnode
函数进行差别比照更新,否则删除旧节点,减少新节点。
if (sameVnode(oldVNode, vnode)) { patchVnode(oldVNode, vnode);} else { removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1); addVnodes(parentElm, null, vnode, 0, vnode.length - 1);}
sameVnode
function sameVnode () { return ( a.key === b.key && a.tag === b.tag && a.isComment === b.isComment && (!!a.data) === (!!b.data) && sameInputType(a, b) )}function sameInputType (a, b) { if (a.tag !== 'input') return true let i const typeA = (i = a.data) && (i = i.attrs) && i.type const typeB = (i = b.data) && (i = i.attrs) && i.type return typeA === typeB}
sameVnode
其实很简略,只有当 key
、 tag
、 isComment
(是否为正文节点)、 data
同时定义(或不定义),同时满足当标签类型为 input
的时候 type
雷同(某些浏览器不反对动静批改类型,所以他们被视为不同类型)即可。
patchVnode
参考文章
- answershuto/VueDemo