From d99139e84369b1a7749f4e26f4a76b685ebe8edf Mon Sep 17 00:00:00 2001 From: daiwei Date: Mon, 1 Apr 2024 16:47:52 +0800 Subject: [PATCH 1/3] fix(Transtion): ensure the KeepAlive children unmount w/ out-in mode --- .../components/BaseTransition.spec.ts | 37 +++++++++++++++++++ .../src/components/BaseTransition.ts | 7 ++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/__tests__/components/BaseTransition.spec.ts b/packages/runtime-core/__tests__/components/BaseTransition.spec.ts index 7c389fe1ede..3184c9c9c6a 100644 --- a/packages/runtime-core/__tests__/components/BaseTransition.spec.ts +++ b/packages/runtime-core/__tests__/components/BaseTransition.spec.ts @@ -7,6 +7,7 @@ import { h, nextTick, nodeOps, + onUnmounted, ref, render, serialize, @@ -768,6 +769,42 @@ describe('BaseTransition', () => { test('w/ KeepAlive', async () => { await runTestWithKeepAlive(testOutIn) }) + + test('w/ KeepAlive + unmount innerChild', async () => { + const unmountSpy = vi.fn() + const includeRef = ref(['TrueBranch']) + const trueComp = { + name: 'TrueBranch', + setup() { + onUnmounted(unmountSpy) + const count = ref(0) + return () => h('div', count.value) + }, + } + + const toggle = ref(true) + const { props } = mockProps({ mode: 'out-in' }, true /*withKeepAlive*/) + const root = nodeOps.createElement('div') + const App = { + render() { + return h(BaseTransition, props, () => { + return h( + KeepAlive, + { include: includeRef.value }, + toggle.value ? h(trueComp) : h('div'), + ) + }) + }, + } + render(h(App), root) + + // trigger toggle + toggle.value = false + includeRef.value = [] + + await nextTick() + expect(unmountSpy).toHaveBeenCalledTimes(1) + }) }) // #6835 diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index e99fe0e496c..8fd04dd56f3 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -13,12 +13,13 @@ import { isSameVNodeType, } from '../vnode' import { warn } from '../warning' -import { isKeepAlive } from './KeepAlive' +import { KeepAlive, isKeepAlive } from './KeepAlive' import { toRaw } from '@vue/reactivity' import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling' import { PatchFlags, ShapeFlags, isArray } from '@vue/shared' import { onBeforeUnmount, onMounted } from '../apiLifecycle' import type { RendererElement } from '../renderer' +import { h } from '../h' type Hook void> = T | T[] @@ -452,9 +453,7 @@ export function resolveTransitionHooks( // unmounted. function emptyPlaceholder(vnode: VNode): VNode | undefined { if (isKeepAlive(vnode)) { - vnode = cloneVNode(vnode) - vnode.children = null - return vnode + return h(KeepAlive, vnode.props, () => null) } } From fd0e206366cdedf26f24a2779ea418a173e75c02 Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 2 Apr 2024 10:03:47 +0800 Subject: [PATCH 2/3] chore: improve code --- packages/runtime-core/src/components/BaseTransition.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index 8fd04dd56f3..dfdc3145329 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -16,7 +16,7 @@ import { warn } from '../warning' import { KeepAlive, isKeepAlive } from './KeepAlive' import { toRaw } from '@vue/reactivity' import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling' -import { PatchFlags, ShapeFlags, isArray } from '@vue/shared' +import { PatchFlags, ShapeFlags, extend, isArray } from '@vue/shared' import { onBeforeUnmount, onMounted } from '../apiLifecycle' import type { RendererElement } from '../renderer' import { h } from '../h' @@ -453,7 +453,9 @@ export function resolveTransitionHooks( // unmounted. function emptyPlaceholder(vnode: VNode): VNode | undefined { if (isKeepAlive(vnode)) { - return h(KeepAlive, vnode.props, () => null) + vnode = cloneVNode(vnode) + extend(vnode, h(KeepAlive, vnode.props, { default: () => null })) + return vnode } } From f19eed1e6b291d108f735d77e7a085fa82373ddd Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 3 Apr 2024 09:15:21 +0800 Subject: [PATCH 3/3] chore: improve code --- packages/runtime-core/src/components/BaseTransition.ts | 7 +++---- packages/runtime-core/src/components/KeepAlive.ts | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index dfdc3145329..e99fe0e496c 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -13,13 +13,12 @@ import { isSameVNodeType, } from '../vnode' import { warn } from '../warning' -import { KeepAlive, isKeepAlive } from './KeepAlive' +import { isKeepAlive } from './KeepAlive' import { toRaw } from '@vue/reactivity' import { ErrorCodes, callWithAsyncErrorHandling } from '../errorHandling' -import { PatchFlags, ShapeFlags, extend, isArray } from '@vue/shared' +import { PatchFlags, ShapeFlags, isArray } from '@vue/shared' import { onBeforeUnmount, onMounted } from '../apiLifecycle' import type { RendererElement } from '../renderer' -import { h } from '../h' type Hook void> = T | T[] @@ -454,7 +453,7 @@ export function resolveTransitionHooks( function emptyPlaceholder(vnode: VNode): VNode | undefined { if (isKeepAlive(vnode)) { vnode = cloneVNode(vnode) - extend(vnode, h(KeepAlive, vnode.props, { default: () => null })) + vnode.children = null return vnode } } diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index db6088cf5c6..7697096bcd7 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -254,7 +254,7 @@ const KeepAliveImpl: ComponentOptions = { pendingCacheKey = null if (!slots.default) { - return null + return (current = null) } const children = slots.default()