You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionupdateChildren(parentElm,oldCh,newCh,insertedVnodeQueue,removeOnly){
...
while(oldStartIdx<=oldEndIdx&&newStartIdx<=newEndIdx){if(isUndef(oldStartVnode)){
...
}elseif(isUndef(oldEndVnode)){
...
}elseif(sameVnode(oldStartVnode,newStartVnode)){
...
}elseif(sameVnode(oldEndVnode,newEndVnode)){
...
}elseif(sameVnode(oldStartVnode,newEndVnode)){// Vnode moved right
...
}elseif(sameVnode(oldEndVnode,newStartVnode)){// Vnode moved left
...
}else{if(isUndef(oldKeyToIdx))oldKeyToIdx=createKeyToOldIdx(oldCh,oldStartIdx,oldEndIdx)idxInOld=isDef(newStartVnode.key)
? oldKeyToIdx[newStartVnode.key]
: findIdxInOld(newStartVnode,oldCh,oldStartIdx,oldEndIdx)if(isUndef(idxInOld)){// New elementcreateElm(newStartVnode,insertedVnodeQueue,parentElm,oldStartVnode.elm,false,newCh,newStartIdx)}else{vnodeToMove=oldCh[idxInOld]if(sameVnode(vnodeToMove,newStartVnode)){patchVnode(vnodeToMove,newStartVnode,insertedVnodeQueue,newCh,newStartIdx)oldCh[idxInOld]=undefinedcanMove&&nodeOps.insertBefore(parentElm,vnodeToMove.elm,oldStartVnode.elm)}else{// same key but different element. treat as new elementcreateElm(newStartVnode,insertedVnodeQueue,parentElm,oldStartVnode.elm,false,newCh,newStartIdx)}}newStartVnode=newCh[++newStartIdx]}}
...
}
一、Key是什么
开始之前,我们先还原两个实际工作场景
v-for
时,需要给单元加上key
+new Date()
生成的时间戳作为key
,手动强制触发重新渲染那么这背后的逻辑是什么,
key
的作用又是什么?一句话来讲
场景背后的逻辑
当我们在使用
v-for
时,需要给单元加上key
如果不用key,Vue会采用就地复地原则:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。
如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed
用
+new Date()
生成的时间戳作为key
,手动强制触发重新渲染二、设置key与不设置key区别
举个例子:
创建一个实例,2秒后往
items
数组插入数据在不使用
key
的情况,vue
会进行这样的操作:分析下整体流程:
patch
,但数据相同,不发生dom
操作patch
,但数据相同,不发生dom
操作patch
,数据不同,发生dom
操作patch
,数据不同,发生dom
操作patch
,数据不同,发生dom
操作DOM
中一共发生了3次更新,1次插入操作
在使用
key
的情况:vue
会进行这样的操作:patch
,但数据相同,不发生dom
操作patch
,但数据相同,不发生dom
操作patch
,但数据相同,不发生dom
操作patch
,但数据相同,不发生dom
操作patch
,但数据相同,不发生dom
操作一共发生了0次更新,1次插入操作
通过上面两个小例子,可见设置
key
能够大大减少对页面的DOM
操作,提高了diff
效率设置key值一定能提高diff效率吗?
其实不然,文档中也明确表示
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
建议尽可能在使用
v-for
时提供key
,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升三、原理分析
源码位置:core/vdom/patch.js
这里判断是否为同一个
key
,首先判断的是key
值是否相等如果没有设置key
,那么key
为undefined
,这时候undefined
是恒等于undefined
updateChildren
方法中会对新旧vnode
进行diff
,然后将比对出的结果用来更新真实的DOM
参考文献
The text was updated successfully, but these errors were encountered: