From d6b96965dac19b88109e676896b9f50b1fc0fef3 Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 14 Apr 2026 07:49:11 +0800 Subject: [PATCH] fix(runtime-vapor): remove teleport with insertion parent close #14717 --- .../__tests__/components/Teleport.spec.ts | 41 +++++++++++++++++++ packages/runtime-vapor/src/component.ts | 1 + 2 files changed, 42 insertions(+) diff --git a/packages/runtime-vapor/__tests__/components/Teleport.spec.ts b/packages/runtime-vapor/__tests__/components/Teleport.spec.ts index c41ab098f0e..39548231f0b 100644 --- a/packages/runtime-vapor/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-vapor/__tests__/components/Teleport.spec.ts @@ -1313,6 +1313,47 @@ function runSharedTests(deferMode: boolean): void { expect(root.innerHTML).toBe('
foo
') }) + test('should remove teleport with insertion parent when toggled off', async () => { + const root = document.createElement('div') + const target = document.createElement('div') + const show = ref(true) + + const { mount } = define({ + setup() { + return createIf( + () => show.value, + () => { + const n0 = template('
')() + setInsertionState(n0 as any, null, 0, true) + createComponent( + VaporTeleport, + { + to: () => target, + }, + { + default: () => template('')(), + }, + ) + return n0 + }, + ) + }, + }).create() + + mount(root) + + expect(root.innerHTML).toBe( + '
', + ) + expect(target.innerHTML).toBe('') + + show.value = false + await nextTick() + + expect(root.innerHTML).toBe('') + expect(target.innerHTML).toBe('') + }) + test('unmount previous sibling node inside target node', async () => { const root = document.createElement('div') const parentShow = ref(false) diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts index b22e7055f5b..b2905acd1a8 100644 --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@ -331,6 +331,7 @@ export function createComponent( // teleport if (isVaporTeleport(component)) { const frag = component.process(rawProps!, rawSlots!) + onScopeDispose(() => remove(frag), true) if (!isHydrating) { if (_insertionParent) insert(frag, _insertionParent, _insertionAnchor) } else {