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
// 删除剩余的旧节点removeVnodes(oldCh,oldStartIdx,oldEndIdx)functionremoveVnodes(vnodes,startIdx,endIdx){for(;startIdx<=endIdx;++startIdx){constch=vnodes[startIdx]if(isDef(ch)){if(isDef(ch.tag)){removeAndInvokeRemoveHook(ch)invokeDestroyHook(ch)}else{// Text noderemoveNode(ch.elm)}}}}
前言
在
vue
中,首先是将模板编译成虚拟DOM
,然后再将虚拟DOM
转为真实的DOM
。当我们的页面有更新时,仅仅是改变了很小的一部分,要去替换整体旧的DOM
的话,势必会影响性能和用户体验的。所以vue
中使用diff
算法来优化DOM
的更新渲染。createPatchFunction
在将虚拟
DOM
转为真实DOM
中,有一个很重要的函数,就是createPatchFunction
。其中又有一段很重要的代码。这里分为三种情况,
patchVnode
前两种情况,之前的文章中,已经讲过。接下来,我们就详细看看
patchVnode
patchVnode
patchVnode
主要做了两件事,1、判断新节点是否是文本节点,如果是文本节点,就需要判断与旧节点上的文本节点是否一致。不一致的时候,就需要更新节点上的文本。
2、是当新节点不是文本节点时候,就需要对新旧节点的子元素进行判断了。这里有四种情况:
children
:使用updateChildren
比较两个children
。children
:清空旧节点上的文本,然后将新节点创建为真实DOM
后,插入到父节点。children
:删除节点上的children
。updateChildren
重点看下
updateChildren
这个函数,可以看出
updateChildren
主要的作用是比较新旧子节点,分为5种情况:若旧开始节点与新开始节点相等时,说明旧开始节点的位置是对的,不需要更新该节点。之后是将旧开始节点和新开始节点的下标后移一位。
若旧结束节点与新结束节点相等,说明旧节点的位置是对的,不需要更新该节点。之后是将旧结束节点和新结束节点的下标前移一位。
若旧开始节点与新结束节点相等,说明旧开始节点的位置不对了,需要移动到
oldEndVnode
后面。然后将旧开始节点的下标后移一位,新结束节点的下标前移一位。若旧结束节点与新开始节点相等,说明旧结束节点需要移动到
oldStartVnode
前面。然后将旧结束节点前移一位,新开始节点位置后移一位。5、
key
值查找当前面四种比较都不行的时候,则会去通过
key
值进行查找。查找时候是当前的新节点,去遍历旧节点数组,找到相同的旧节点,然后将其移到oldStartVnode
前面。大致流程是:处理剩余节点
接着就是处理余下的新旧节点。有两种情况:
将剩余的旧节点,逐个删除即可。
逐个创建剩余的新节点。有个问题是,将剩余的新节点创建好后,插入到哪里呢?
我们可以看到,
refElm
是获取新节点最后一个节点。如果
refElm
存在的话,说明最后一个节点之前被处理过,那么剩余的新节点插入到refElm
前面即可。如果
refElm
不存在,则将剩余的新节点插入到父节点孩子的末尾。本文到此也就结束了,相信大家也对
vue 中 diff
算法有一定了解。结束的结束,有个小问题,大家觉得v-for 中 key
值的作用是什么呢?The text was updated successfully, but these errors were encountered: