Ver Fonte

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

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

* fix(teleport): targetAnchor should also be removed when unmounted
há 5 anos atrás
pai
commit
21d1288133

+ 16 - 12
packages/runtime-core/__tests__/components/Teleport.spec.ts

@@ -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', () => {

+ 15 - 6
packages/runtime-core/src/components/Teleport.ts

@@ -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])
+        }
       }
     }
   },

+ 3 - 11
packages/runtime-core/src/renderer.ts

@@ -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) {