vue diff算法全理会(5)

5、sameVnode(oldStartVnode, newEndVnode),这里判定oldCh起始指针指向的工具和newCh竣事指针所指向的工具是否可以复用。假如返回真,则先挪用patchVnode要领复用dom元素并递归较量子元素,因为复用的元素在newCh中是竣事指针所指的元素,所以把它插入到oldEndVnode.elm的前面。最后oldCh的起始指针后移一位,newCh的起始指针别离前移一位。

else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue) canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm)) oldStartVnode = oldCh[++oldStartIdx] newEndVnode = newCh[--newEndIdx] }

6、sameVnode(oldEndVnode, newStartVnode),这里判定oldCh竣事指针指向的工具和newCh起始指针所指向的工具是否可以复用。假如返回真,则先挪用patchVnode要领复用dom元素并递归较量子元素,因为复用的元素在newCh中是起始指针所指的元素,所以把它插入到oldStartVnode.elm的前面。最后oldCh的竣事指针前移一位,newCh的起始指针别离后移一位。

else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue) canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm) oldEndVnode = oldCh[--oldEndIdx] newStartVnode = newCh[++newStartIdx] }

7、假如上述六种环境都不满意,则走到这里。前面的较量都是头尾组合的较量,这里的环境,稍微越发巨大一些,其实主要就是按照key值来复用元素。

① 遍历oldCh数组,找出个中有key的工具,并以key为键,索引值为value,生成新的工具oldKeyToIdx。

if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx) function createKeyToOldIdx (children, beginIdx, endIdx) { let i, key const map = {} for (i = beginIdx; i <= endIdx; ++i) { key = children[i].key if (isDef(key)) map[key] = i } return map }

② 查询newStartVnode是否有key值,并查找oldKeyToIdx是否有沟通的key。

idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null

③ 假如newStartVnode没有key或oldKeyToIdx没有沟通的key,则挪用createElm要领建设新元素,newCh的起始索引后移一位。

if (isUndef(idxInOld)) { // New element createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm) newStartVnode = newCh[++newStartIdx] }

④ elmToMove生存的是要移动的元素,假如sameVnode(elmToMove, newStartVnode)返回真,说明可以复用,这时先挪用patchVnode要领复用dom元素并递归较量子元素,重置oldCh中相对付的元素为undefined,然后把当前元素插入到oldStartVnode.elm前面,newCh的起始索引后移一位。假如sameVnode(elmToMove, newStartVnode)返回假,譬喻tag名差异,则挪用createElm要领建设新元素,newCh的起始索引后移一位。

elmToMove = oldCh[idxInOld] if (sameVnode(elmToMove, newStartVnode)) { patchVnode(elmToMove, newStartVnode, insertedVnodeQueue) oldCh[idxInOld] = undefined canMove && nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm) newStartVnode = newCh[++newStartIdx] } else { // same key but different element. treat as new element createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm) newStartVnode = newCh[++newStartIdx] }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsjfdz.html