diff --git a/packages/runtime-core/__tests__/components/Teleport.spec.ts b/packages/runtime-core/__tests__/components/Teleport.spec.ts index 79125cd04df..1cf83dd35d3 100644 --- a/packages/runtime-core/__tests__/components/Teleport.spec.ts +++ b/packages/runtime-core/__tests__/components/Teleport.spec.ts @@ -719,6 +719,36 @@ describe('renderer: teleport', () => { expect(root.innerHTML).toBe('') }) + test('skip unmount children if teleport not disabled & target missing', async () => { + const root = document.createElement('div') + const childShow = ref(true) + + const Comp = { + setup() { + return () => h(Teleport, { to: null }, [h('div', 'foo')]) + }, + } + + const App = defineComponent({ + setup() { + return () => { + return h(Fragment, { key: 0 }, [ + childShow.value ? h(Comp) : createCommentVNode('v-if'), + ]) + } + }, + }) + + domRender(h(App), root) + expect('Invalid Teleport target: null').toHaveBeenWarned() + expect('Invalid Teleport target on mount').toHaveBeenWarned() + expect(root.innerHTML).toBe('') + + childShow.value = false + await nextTick() + expect(root.innerHTML).toBe('') + }) + test('accessing template refs inside teleport', async () => { const target = nodeOps.createElement('div') const tRef = ref() diff --git a/packages/runtime-core/src/components/Teleport.ts b/packages/runtime-core/src/components/Teleport.ts index fe6fa36c1ca..7dab240e3ae 100644 --- a/packages/runtime-core/src/components/Teleport.ts +++ b/packages/runtime-core/src/components/Teleport.ts @@ -308,16 +308,20 @@ export const TeleportImpl = { target, props, } = vnode + // an unmounted teleport should always unmount its children whether it's disabled or not + doRemove && hostRemove(anchor!) + + // skip unmount if not disabled & target missing (children not rendered) + const disabled = isTeleportDisabled(props) + if (!disabled && !target) return if (target) { hostRemove(targetStart!) hostRemove(targetAnchor!) } - // 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) + const shouldRemove = doRemove || !disabled for (let i = 0; i < (children as VNode[]).length; i++) { const child = (children as VNode[])[i] unmount(