我看的是 vue3.2.31 版本的源码,diff 算法具体的位置在
packages/runtime-core/src/render.ts
文件中,源码中一些部分我已经做了注释
1、Vue源码对于key的判断
-
下面是
patchChildren
方法(进行新旧VNode节点比对)的源码,其位置在vue3源码(我看的源码是vue3.2.31版本)的:packages/runtime-core/src/render.ts
文件的1590-1691行// 进行 VNode 节点的比对 const patchChildren: PatchChildrenFn = ( n1, n2, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized = false ) => { const c1 = n1 && n1.children const prevShapeFlag = n1 ? n1.shapeFlag : 0 const c2 = n2.children // 这个 patchFlag,就是一个判断渲染的节点上是包含 key 的一个标识符 const { patchFlag, shapeFlag } = n2 if (patchFlag > 0) { if (patchFlag & PatchFlags.KEYED_FRAGMENT) { // 当节点上面存在 key,执行的是 patchKeyedChildren 方法 patchKeyedChildren( c1 as VNode[], c2 as VNodeArrayChildren, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized ) return } else if (patchFlag & PatchFlags.UNKEYED_FRAGMENT) { // 当前节点上不存在 key,执行的是 patchUnkeyedChildren 方法 patchUnkeyedChildren**( c1 as VNode[], c2 as VNodeArrayChildren, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized ) return } } // children has 3 possibilities: text, array or no children. if (shapeFlag & ShapeFlags.TEXT_CHILDREN) { // text children fast path if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) { unmountChildren(c1 as VNode[], parentComponent, parentSuspense) } if (c2 !== c1) { hostSetElementText(container, c2 as string) } } else { if (prevShapeFlag & ShapeFlags.ARRAY_CHILDREN) { // prev children was array if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { // two arrays, cannot assume anything, do full diff patchKeyedChildren( c1 as VNode[], c2 as VNodeArrayChildren, container, anchor, parentComponent, parentSuspense, isSVG, slotScopeIds, optimized ) } else { // no new children, just unmount old unmountChildren(c1 as VNode[], parentComponent, parentSuspense, true) } } else { // prev children was text OR null // new children is array OR null if (prevShapeFlag & ShapeFlags.TEXT_CHILDREN) { hostSetElementText(container, '') } // mount new if array if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { mountChildren( c2 as VNodeArrayChildren, container, anchor,