From 6575a6e445c10eed7b20d3b0ae366c7730598207 Mon Sep 17 00:00:00 2001 From: Rairn <958414905@qq.com> Date: Mon, 14 Nov 2022 11:34:42 +0800 Subject: [PATCH] fix(hmr/transition): fix transition elements disappearing after reloading component (#7121) --- packages/runtime-core/__tests__/hmr.spec.ts | 69 +++++++++++++++++++ .../src/components/BaseTransition.ts | 5 +- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index db713a3f276..d7c54cdc27d 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -218,6 +218,75 @@ describe('hot module replacement', () => { expect(deactiveSpy).toHaveBeenCalledTimes(1) }) + // #7121 + test('reload KeepAlive slot in Transition', async () => { + const root = nodeOps.createElement('div') + const childId = 'test-transition-keep-alive-reload' + const unmountSpy = jest.fn() + const mountSpy = jest.fn() + const activeSpy = jest.fn() + const deactiveSpy = jest.fn() + + const Child: ComponentOptions = { + __hmrId: childId, + data() { + return { count: 0 } + }, + unmounted: unmountSpy, + render: compileToFunction(`
{{ count }}
`) + } + createRecord(childId, Child) + + const Parent: ComponentOptions = { + components: { Child }, + data() { + return { toggle: true } + }, + render: compileToFunction( + `` + ) + } + + render(h(Parent), root) + expect(serializeInner(root)).toBe(`
0
`) + + reload(childId, { + __hmrId: childId, + data() { + return { count: 1 } + }, + mounted: mountSpy, + unmounted: unmountSpy, + activated: activeSpy, + deactivated: deactiveSpy, + render: compileToFunction(`
{{ count }}
`) + }) + await nextTick() + expect(serializeInner(root)).toBe(`
1
`) + expect(unmountSpy).toHaveBeenCalledTimes(1) + expect(mountSpy).toHaveBeenCalledTimes(1) + expect(activeSpy).toHaveBeenCalledTimes(1) + expect(deactiveSpy).toHaveBeenCalledTimes(0) + + // should not unmount when toggling + triggerEvent(root.children[1] as TestElement, 'click') + await nextTick() + expect(serializeInner(root)).toBe(``) + expect(unmountSpy).toHaveBeenCalledTimes(1) + expect(mountSpy).toHaveBeenCalledTimes(1) + expect(activeSpy).toHaveBeenCalledTimes(1) + expect(deactiveSpy).toHaveBeenCalledTimes(1) + + // should not mount when toggling + triggerEvent(root.children[1] as TestElement, 'click') + await nextTick() + expect(serializeInner(root)).toBe(`
1
`) + expect(unmountSpy).toHaveBeenCalledTimes(1) + expect(mountSpy).toHaveBeenCalledTimes(1) + expect(activeSpy).toHaveBeenCalledTimes(2) + expect(deactiveSpy).toHaveBeenCalledTimes(1) + }) + test('reload class component', async () => { const root = nodeOps.createElement('div') const childId = 'test4-child' diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index 9cb80b94ef0..5914665bb98 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -473,7 +473,10 @@ function emptyPlaceholder(vnode: VNode): VNode | undefined { function getKeepAliveChild(vnode: VNode): VNode | undefined { return isKeepAlive(vnode) - ? vnode.children + ? // #7121 avoid the result is expired during HMR + vnode.component + ? vnode.component.subTree + : vnode.children ? ((vnode.children as VNodeArrayChildren)[0] as VNode) : undefined : vnode