Skip to content

Commit 7769513

Browse files
authored
fix(Teleport): component with multi roots should be removed when unmounted (#3157)
fix #3156
1 parent 0a583d5 commit 7769513

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

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

+20
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,26 @@ describe('renderer: teleport', () => {
147147
testUnmount({ to: null, disabled: true })
148148
})
149149

150+
test('component with multi roots should be removed when unmounted', () => {
151+
const target = nodeOps.createElement('div')
152+
const root = nodeOps.createElement('div')
153+
154+
const Comp = {
155+
render() {
156+
return [h('p'), h('p')]
157+
}
158+
}
159+
160+
render(
161+
h(() => [h(Teleport, { to: target }, h(Comp)), h('div', 'root')]),
162+
root
163+
)
164+
expect(serializeInner(target)).toMatchInlineSnapshot(`"<p></p><p></p>"`)
165+
166+
render(null, root)
167+
expect(serializeInner(target)).toBe('')
168+
})
169+
150170
test('multiple teleport with same target', () => {
151171
const target = nodeOps.createElement('div')
152172
const root = nodeOps.createElement('div')

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

+12-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface TeleportProps {
2121

2222
export const isTeleport = (type: any): boolean => type.__isTeleport
2323

24-
export const isTeleportDisabled = (props: VNode['props']): boolean =>
24+
const isTeleportDisabled = (props: VNode['props']): boolean =>
2525
props && (props.disabled || props.disabled === '')
2626

2727
const isTargetSVG = (target: RendererElement): boolean =>
@@ -218,7 +218,10 @@ export const TeleportImpl = {
218218

219219
remove(
220220
vnode: VNode,
221-
{ r: remove, o: { remove: hostRemove } }: RendererInternals,
221+
parentComponent: ComponentInternalInstance | null,
222+
parentSuspense: SuspenseBoundary | null,
223+
optimized: boolean,
224+
{ um: unmount, o: { remove: hostRemove } }: RendererInternals,
222225
doRemove: Boolean
223226
) {
224227
const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode
@@ -232,7 +235,13 @@ export const TeleportImpl = {
232235
hostRemove(anchor!)
233236
if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
234237
for (let i = 0; i < (children as VNode[]).length; i++) {
235-
remove((children as VNode[])[i])
238+
unmount(
239+
(children as VNode[])[i],
240+
parentComponent,
241+
parentSuspense,
242+
true,
243+
optimized
244+
)
236245
}
237246
}
238247
}

packages/runtime-core/src/renderer.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -2108,7 +2108,14 @@ function baseCreateRenderer(
21082108
}
21092109

21102110
if (shapeFlag & ShapeFlags.TELEPORT) {
2111-
;(vnode.type as typeof TeleportImpl).remove(vnode, internals, doRemove)
2111+
;(vnode.type as typeof TeleportImpl).remove(
2112+
vnode,
2113+
parentComponent,
2114+
parentSuspense,
2115+
optimized,
2116+
internals,
2117+
doRemove
2118+
)
21122119
}
21132120

21142121
if (doRemove) {

0 commit comments

Comments
 (0)