From 21d128813353fd5d5a5304f8fb885265f5163cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B1=BC?= <31395977+leaon4@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:19:09 +0800 Subject: [PATCH] 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 --- .../__tests__/components/Teleport.spec.ts | 28 +++++++++++-------- .../runtime-core/src/components/Teleport.ts | 21 ++++++++++---- packages/runtime-core/src/renderer.ts | 14 ++-------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index 15afa6db2e7..2307932ed6b 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/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( - `"
teleported
"` - ) + function testUnmount(props: any) { + render( + h(() => [h(Teleport, props, h('div', 'teleported')), h('div', 'root')]), + root + ) + expect(serializeInner(target)).toMatchInlineSnapshot( + props.disabled ? `""` : `"
teleported
"` + ) + + 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', () => { diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index e75455f96f0..7bbad77fbf0 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/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]) + } } } }, diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index f2a35794c37..e12d0242fc8 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/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) {