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