From 2ef016bfe2736df878e7cb2e0e90222e7a8ba73e Mon Sep 17 00:00:00 2001 From: pupu Date: Mon, 22 Aug 2022 21:18:31 +0800 Subject: [PATCH 1/2] fix(teleport): ensure descendent component would be unmounted correctly fix #6347 --- .../__tests__/components/Teleport.spec.ts | 25 ++++++++++++++++ .../runtime-core/src/components/Teleport.ts | 29 +++++++++---------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index e5f76e30700..e1f1db2750e 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -168,6 +168,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: jest.fn(), + unmounted: jest.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 06b69aff4ec..054209fd3d1 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -230,7 +230,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 @@ -238,20 +238,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 + ) } } }, From 1c03f710259e5605dc1ddf2a2566fbfb2d94211f Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Tue, 19 Sep 2023 15:48:44 +0800 Subject: [PATCH 2/2] test: replace jest.fn with vi.fn --- packages/runtime-core/__tests__/components/Teleport.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index 3ae31248b3f..c0dbd4cae9c 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -180,8 +180,8 @@ describe('renderer: teleport', () => { render() { return [h('p'), h('p')] }, - beforeUnmount: jest.fn(), - unmounted: jest.fn() + beforeUnmount: vi.fn(), + unmounted: vi.fn() } render(