]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(fragment): perform direct remove when removing fragments
authorEvan You <yyx990803@gmail.com>
Sun, 22 Dec 2019 21:15:16 +0000 (16:15 -0500)
committerEvan You <yyx990803@gmail.com>
Sun, 22 Dec 2019 21:15:16 +0000 (16:15 -0500)
This avoids trying to grab .el from hoisted child nodes (which can
be created by another instance), and also skips transition check
since fragment children cannot have transitions.

packages/runtime-core/src/renderer.ts

index eece7c3544191f7239ac800b7cef04113e92613b..0b86923e860b2051bdb92541689875a81f6ddb25 100644 (file)
@@ -1573,10 +1573,14 @@ export function createRenderer<
   }
 
   function remove(vnode: HostVNode) {
-    const { type, el, anchor, children, transition } = vnode
+    const { type, el, anchor, transition } = vnode
+    if (type === Fragment) {
+      removeFragment(el!, anchor!)
+      return
+    }
+
     const performRemove = () => {
       hostRemove(el!)
-      if (anchor != null) hostRemove(anchor)
       if (
         transition != null &&
         !transition.persisted &&
@@ -1585,11 +1589,7 @@ export function createRenderer<
         transition.afterLeave()
       }
     }
-    if (type === Fragment) {
-      performRemove()
-      removeChildren(children as HostVNode[])
-      return
-    }
+
     if (
       vnode.shapeFlag & ShapeFlags.ELEMENT &&
       transition != null &&
@@ -1607,10 +1607,16 @@ export function createRenderer<
     }
   }
 
-  function removeChildren(children: HostVNode[]) {
-    for (let i = 0; i < children.length; i++) {
-      remove(children[i])
+  function removeFragment(cur: HostNode, end: HostNode) {
+    // For fragments, directly remove all contained DOM nodes.
+    // (fragment child nodes cannot have transition)
+    let next
+    while (cur !== end) {
+      next = hostNextSibling(cur)!
+      hostRemove(cur)
+      cur = next
     }
+    hostRemove(end)
   }
 
   function unmountComponent(