]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): handle dynamicChildren when portal is used as a block
authorEvan You <yyx990803@gmail.com>
Wed, 16 Oct 2019 21:43:33 +0000 (17:43 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 16 Oct 2019 21:43:41 +0000 (17:43 -0400)
packages/runtime-core/src/createRenderer.ts

index d2dd89afce28684e696d4378f588079d3905fd06..0a059c00175e691bd3fe8afd29f733a53d797c0f 100644 (file)
@@ -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,