]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(teleport): targetAnchor should also be removed when unmounted (#2870)
author <31395977+leaon4@users.noreply.github.com>
Tue, 23 Mar 2021 09:19:09 +0000 (17:19 +0800)
committerGitHub <noreply@github.com>
Tue, 23 Mar 2021 09:19:09 +0000 (10:19 +0100)
* fix(teleport): targetAnchor should also be removed when unmounted

* fix(teleport): targetAnchor should also be removed when unmounted

packages/runtime-core/__tests__/components/Teleport.spec.ts
packages/runtime-core/src/components/Teleport.ts
packages/runtime-core/src/renderer.ts

index 15afa6db2e72258fb397339007858d4160543a14..2307932ed6b37a9a600a83a56c51cab97a6b5293 100644 (file)
@@ -128,19 +128,23 @@ describe('renderer: teleport', () => {
     const target = nodeOps.createElement('div')
     const root = nodeOps.createElement('div')
 
-    render(
-      h(() => [
-        h(Teleport, { to: target }, h('div', 'teleported')),
-        h('div', 'root')
-      ]),
-      root
-    )
-    expect(serializeInner(target)).toMatchInlineSnapshot(
-      `"<div>teleported</div>"`
-    )
+    function testUnmount(props: any) {
+      render(
+        h(() => [h(Teleport, props, h('div', 'teleported')), h('div', 'root')]),
+        root
+      )
+      expect(serializeInner(target)).toMatchInlineSnapshot(
+        props.disabled ? `""` : `"<div>teleported</div>"`
+      )
+
+      render(null, root)
+      expect(serializeInner(target)).toBe('')
+      expect(target.children.length).toBe(0)
+    }
 
-    render(null, root)
-    expect(serializeInner(target)).toBe('')
+    testUnmount({ to: target, disabled: false })
+    testUnmount({ to: target, disabled: true })
+    testUnmount({ to: null, disabled: true })
   })
 
   test('multiple teleport with same target', () => {
index e75455f96f042ce7e0cc17138bde75afd0b84e8d..7bbad77fbf0a7f86528d486a2d21b89f8093f6da 100644 (file)
@@ -218,13 +218,22 @@ export const TeleportImpl = {
 
   remove(
     vnode: VNode,
-    { r: remove, o: { remove: hostRemove } }: RendererInternals
+    { r: remove, o: { remove: hostRemove } }: RendererInternals,
+    doRemove: Boolean
   ) {
-    const { shapeFlag, children, anchor } = vnode
-    hostRemove(anchor!)
-    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
-      for (let i = 0; i < (children as VNode[]).length; i++) {
-        remove((children as VNode[])[i])
+    const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
+
+    if (target) {
+      hostRemove(targetAnchor!)
+    }
+
+    // an unmounted teleport should always remove its children if not disabled
+    if (doRemove || !isTeleportDisabled(props)) {
+      hostRemove(anchor!)
+      if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
+        for (let i = 0; i < (children as VNode[]).length; i++) {
+          remove((children as VNode[])[i])
+        }
       }
     }
   },
index f2a35794c377519497a476a6e2a4a73360fb3209..e12d0242fc8ccb8acd30a8debea25636a0b4ea7b 100644 (file)
@@ -57,11 +57,7 @@ import {
   queueEffectWithSuspense,
   SuspenseImpl
 } from './components/Suspense'
-import {
-  isTeleportDisabled,
-  TeleportImpl,
-  TeleportVNode
-} from './components/Teleport'
+import { TeleportImpl, TeleportVNode } from './components/Teleport'
 import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
 import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
 import {
@@ -2111,12 +2107,8 @@ function baseCreateRenderer(
         unmountChildren(children as VNode[], parentComponent, parentSuspense)
       }
 
-      // an unmounted teleport should always remove its children if not disabled
-      if (
-        shapeFlag & ShapeFlags.TELEPORT &&
-        (doRemove || !isTeleportDisabled(vnode.props))
-      ) {
-        ;(vnode.type as typeof TeleportImpl).remove(vnode, internals)
+      if (shapeFlag & ShapeFlags.TELEPORT) {
+        ;(vnode.type as typeof TeleportImpl).remove(vnode, internals, doRemove)
       }
 
       if (doRemove) {