首先从第一个节点开始比较,不管是oldCh还是newCh的起始或者终止节点都不存在sameVnode,同时节点属性中是不带key标记的,因此第一轮的diff完后,newCh的startVnode被添加到oldStartVnode的前面,同时newStartIndex前移一位;

第二轮的diff中,满足sameVnode(oldStartVnode, newStartVnode),因此对这2个vnode进行diff,最后将patch打到oldStartVnode上,同时oldStartVnode和newStartIndex都向前移动一位

第三轮的diff中,满足sameVnode(oldEndVnode, newStartVnode),那么首先对oldEndVnode和newStartVnode进行diff,并对oldEndVnode进行patch,并完成oldEndVnode移位的操作,最后newStartIndex前移一位,oldStartVnode后移一位;

第四轮的diff中,过程同步骤3;

第五轮的diff中,同过程1;

遍历的过程结束后,newStartIdx > newEndIdx,说明此时oldCh存在多余的节点,那么最后就需要将这些多余的节点删除。

在vnode不带key的情况下,每一轮的diff过程当中都是起始和结束节点进行比较,直到oldCh或者newCh被遍历完。而当为vnode引入key属性后,在每一轮的diff过程中,当起始和结束节点都没有找到sameVnode时,首先对oldCh中进行key值与索引的映射:
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : nullcreateKeyToOldIdx方法,用以将oldCh中的key属性作为键,而对应的节点的索引作为值。然后再判断在newStartVnode的属性中是否有key,且是否在oldKeyToIndx中找到对应的节点。
如果不存在这个key,那么就将这个newStartVnode作为新的节点创建且插入到原有的root的子节点中:
if (isUndef(idxInOld)) { // New element
// 创建新的dom节点
// 插入到oldStartVnode.elm前面
// 参见createElm方法
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
newStartVnode = newCh[++newStartIdx] }
如果存在这个key,那么就取出oldCh中的存在这个key的vnode,然后再进行diff的过程:
elmToMove = oldCh[idxInOld] /* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && !elmToMove) { // 将找到的key一致的oldVnode再和newStartVnode进行diff
if (sameVnode(elmToMove, newStartVnode)) {










