diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index 7371f53f7b6..c0dbd4cae9c 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -172,6 +172,31 @@ describe('renderer: teleport', () => { expect(serializeInner(target)).toBe('') }) + // #6347 + test('descendent component should be unmounted when teleport is disabled and unmounted', () => { + const root = nodeOps.createElement('div') + + const CompWithHook = { + render() { + return [h('p'), h('p')] + }, + beforeUnmount: vi.fn(), + unmounted: vi.fn() + } + + render( + h(() => [h(Teleport, { to: null, disabled: true }, h(CompWithHook))]), + root + ) + expect(CompWithHook.beforeUnmount).toBeCalledTimes(0) + expect(CompWithHook.unmounted).toBeCalledTimes(0) + + render(null, root) + + expect(CompWithHook.beforeUnmount).toBeCalledTimes(1) + expect(CompWithHook.unmounted).toBeCalledTimes(1) + }) + test('multiple teleport with same target', () => { const target = nodeOps.createElement('div') const root = nodeOps.createElement('div') diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index 19ccbc5de27..35424c5f618 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -239,7 +239,7 @@ export const TeleportImpl = { parentSuspense: SuspenseBoundary | null, optimized: boolean, { um: unmount, o: { remove: hostRemove } }: RendererInternals, - doRemove: Boolean + doRemove: boolean ) { const { shapeFlag, children, anchor, targetAnchor, target, props } = vnode @@ -247,20 +247,19 @@ export const TeleportImpl = { 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++) { - const child = (children as VNode[])[i] - unmount( - child, - parentComponent, - parentSuspense, - true, - !!child.dynamicChildren - ) - } + // an unmounted teleport should always unmount its children whether it's disabled or not + doRemove && hostRemove(anchor!) + if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) { + const shouldRemove = doRemove || !isTeleportDisabled(props) + for (let i = 0; i < (children as VNode[]).length; i++) { + const child = (children as VNode[])[i] + unmount( + child, + parentComponent, + parentSuspense, + shouldRemove, + !!child.dynamicChildren + ) } } },