} else {
vnodeToMove = oldCh[idxInOld] if (sameVnode(vnodeToMove, newStartVnode)) {
patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
oldCh[idxInOld] = undefined
canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
} else {
// same key but different element. treat as new element
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
}
}
那么设置key值就一定能提高diff效率吗?
答案是否定的
`<div v-for="i in arr">{{ i }}</div>`// 如果我们的数组是这样的
[1, 2, 3, 4, 5]
// 它的渲染结果是这样的
`<div>1</div>` // key: undefined
`<div>2</div>` // key: undefined
`<div>3</div>` // key: undefined
`<div>4</div>` // key: undefined
`<div>5</div>` // key: undefined
// 将它打乱
[4, 1, 3, 5, 2]
// 渲染结果是这样的 期间只发生了DOM节点的文本内容的更新
`<div>4</div>` // key: undefined
`<div>1</div>` // key: undefined
`<div>3</div>` // key: undefined
`<div>5</div>` // key: undefined
`<div>2</div>` // key: undefined
// 如果我们给这个数组每一项都设置了唯一的key
[{id: 'A', value: 1}, {id: 'B', value: 2}, {id: 'C', value: 3}, {id: 'D', value: 4}, {id: 'E', value: 5}]
// 它的渲染结果应该是这样的
`<div>1</div>` // key: A
`<div>2</div>` // key: B
`<div>3</div>` // key: C
`<div>4</div>` // key: D
`<div>5</div>` // key: E
// 将它打乱
[{id: 'D', value: 4}, {id: 'A', value: 1}, {id: 'C', value: 3}, {id: 'E', value: 5}, {id: 'B', value: 2}]
// 渲染结果是这样的 期间只发生了DOM节点的移动
`<div>4</div>` // key: D
`<div>1</div>` // key: A
`<div>3</div>` // key: C
`<div>5</div>` // key: E
`<div>2</div>` // key: B
我们给数组设置了key之后数组的diff效率真的变高了吗?
并没有,因为在简单模板的数组渲染中,新旧节点的key都为undefined,根据sameVnode的判断条件,这些新旧节点的key、tag等属性全部相同,所以在sameVnode(oldStartVnode, newStartVnode)这一步的时候就已经判定为对应的节点(不再执行头尾交叉对比),然后直接进行patchVnode,根本没有走后面的那些else。每一次循环新旧节点都是相对应的,只需要更新其内的文本内容就可以完成DOM更新,这种原地复用的效率无疑是最高的。
而当我们设置了key之后,则会根据头尾交叉对比结果去执行下面的if else,进行判断之后还需要执行insertBefore等方法移动真实DOM的节点的位置或者进行DOM节点的添加和删除,这样的查找复用开销肯定要比不带key直接原地复用的开销要高。










