Skip to content

Commit 21d1288

Browse files
authored
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
1 parent 3b3a9a1 commit 21d1288

File tree

3 files changed

+34
-29
lines changed

3 files changed

+34
-29
lines changed

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

+16-12
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,23 @@ describe('renderer: teleport', () => {
128128
const target = nodeOps.createElement('div')
129129
const root = nodeOps.createElement('div')
130130

131-
render(
132-
h(() => [
133-
h(Teleport, { to: target }, h('div', 'teleported')),
134-
h('div', 'root')
135-
]),
136-
root
137-
)
138-
expect(serializeInner(target)).toMatchInlineSnapshot(
139-
`"<div>teleported</div>"`
140-
)
131+
function testUnmount(props: any) {
132+
render(
133+
h(() => [h(Teleport, props, h('div', 'teleported')), h('div', 'root')]),
134+
root
135+
)
136+
expect(serializeInner(target)).toMatchInlineSnapshot(
137+
props.disabled ? `""` : `"<div>teleported</div>"`
138+
)
139+
140+
render(null, root)
141+
expect(serializeInner(target)).toBe('')
142+
expect(target.children.length).toBe(0)
143+
}
141144

142-
render(null, root)
143-
expect(serializeInner(target)).toBe('')
145+
testUnmount({ to: target, disabled: false })
146+
testUnmount({ to: target, disabled: true })
147+
testUnmount({ to: null, disabled: true })
144148
})
145149

146150
test('multiple teleport with same target', () => {

packages/runtime-core/src/components/Teleport.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,22 @@ export const TeleportImpl = {
218218

219219
remove(
220220
vnode: VNode,
221-
{ r: remove, o: { remove: hostRemove } }: RendererInternals
221+
{ r: remove, o: { remove: hostRemove } }: RendererInternals,
222+
doRemove: Boolean
222223
) {
223-
const { shapeFlag, children, anchor } = vnode
224-
hostRemove(anchor!)
225-
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
226-
for (let i = 0; i < (children as VNode[]).length; i++) {
227-
remove((children as VNode[])[i])
224+
const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
225+
226+
if (target) {
227+
hostRemove(targetAnchor!)
228+
}
229+
230+
// an unmounted teleport should always remove its children if not disabled
231+
if (doRemove || !isTeleportDisabled(props)) {
232+
hostRemove(anchor!)
233+
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
234+
for (let i = 0; i < (children as VNode[]).length; i++) {
235+
remove((children as VNode[])[i])
236+
}
228237
}
229238
}
230239
},

packages/runtime-core/src/renderer.ts

+3-11
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,7 @@ import {
5757
queueEffectWithSuspense,
5858
SuspenseImpl
5959
} from './components/Suspense'
60-
import {
61-
isTeleportDisabled,
62-
TeleportImpl,
63-
TeleportVNode
64-
} from './components/Teleport'
60+
import { TeleportImpl, TeleportVNode } from './components/Teleport'
6561
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
6662
import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
6763
import {
@@ -2111,12 +2107,8 @@ function baseCreateRenderer(
21112107
unmountChildren(children as VNode[], parentComponent, parentSuspense)
21122108
}
21132109

2114-
// an unmounted teleport should always remove its children if not disabled
2115-
if (
2116-
shapeFlag & ShapeFlags.TELEPORT &&
2117-
(doRemove || !isTeleportDisabled(vnode.props))
2118-
) {
2119-
;(vnode.type as typeof TeleportImpl).remove(vnode, internals)
2110+
if (shapeFlag & ShapeFlags.TELEPORT) {
2111+
;(vnode.type as typeof TeleportImpl).remove(vnode, internals, doRemove)
21202112
}
21212113

21222114
if (doRemove) {

0 commit comments

Comments
 (0)