diff --git a/packages/runtime-core/src/createRenderer.ts b/packages/runtime-core/src/createRenderer.ts index d2dd89afc..0a059c001 100644 --- a/packages/runtime-core/src/createRenderer.ts +++ b/packages/runtime-core/src/createRenderer.ts @@ -495,25 +495,14 @@ export function createRenderer< } if (dynamicChildren != null) { - // children fast path - const oldDynamicChildren = n1.dynamicChildren! - for (let i = 0; i < dynamicChildren.length; i++) { - const oldVNode = oldDynamicChildren[i] - patch( - oldVNode, - dynamicChildren[i], - // in the case of a Fragment, we need to provide the actual parent - // of the Fragment itself so it can move its children. In other cases, - // the parent container is not actually used so we just pass the - // block element here to avoid a DOM parentNode call. - oldVNode.type === Fragment ? hostParentNode(oldVNode.el!)! : el, - null, - parentComponent, - parentSuspense, - isSVG, - true - ) - } + patchBlockChildren( + n1.dynamicChildren!, + dynamicChildren, + el, + parentComponent, + parentSuspense, + isSVG + ) } else if (!optimized) { // full diff patchChildren(n1, n2, el, null, parentComponent, parentSuspense, isSVG) @@ -526,6 +515,36 @@ export function createRenderer< } } + // The fast path for blocks. + function patchBlockChildren( + oldChildren: HostVNode[], + newChildren: HostVNode[], + fallbackContainer: HostElement, + parentComponent: ComponentInternalInstance | null, + parentSuspense: HostSuspenseBoundary | null, + isSVG: boolean + ) { + for (let i = 0; i < newChildren.length; i++) { + const oldVNode = oldChildren[i] + patch( + oldVNode, + newChildren[i], + // in the case of a Fragment, we need to provide the actual parent + // of the Fragment itself so it can move its children. In other cases, + // the parent container is not actually used so we just pass the + // block element here to avoid a DOM parentNode call. + oldVNode.type === Fragment + ? hostParentNode(oldVNode.el!)! + : fallbackContainer, + null, + parentComponent, + parentSuspense, + isSVG, + true + ) + } + } + function patchProps( el: HostElement, vnode: HostVNode, @@ -654,6 +673,16 @@ export function createRenderer< const target = (n2.target = n1.target)! if (patchFlag === PatchFlags.TEXT) { hostSetElementText(target, children as string) + } else if (n2.dynamicChildren) { + // fast path when the portal happens to be a block root + patchBlockChildren( + n1.dynamicChildren!, + n2.dynamicChildren, + container, + parentComponent, + parentSuspense, + isSVG + ) } else if (!optimized) { patchChildren( n1,