From 24447e97e2204962d7643d5b9bb1c189e4a47352 Mon Sep 17 00:00:00 2001 From: linzhe Date: Mon, 3 Jun 2024 10:03:07 +0800 Subject: [PATCH 1/6] fix: When the app is unmounted, the effects of suspense in Transition should not be added to queuePostFlushCb --- packages/runtime-core/src/components/BaseTransition.ts | 6 +++--- packages/runtime-core/src/components/Suspense.ts | 4 ++-- packages/runtime-core/src/renderer.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index 070418a19a0..23829afcbd5 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -60,10 +60,10 @@ export interface TransitionHooks { persisted: boolean beforeEnter(el: HostElement): void enter(el: HostElement): void - leave(el: HostElement, remove: () => void): void + leave(el: HostElement, remove: (isUnmounting?: boolean) => void): void clone(vnode: VNode): TransitionHooks // optional - afterLeave?(): void + afterLeave?(isUnmounting?: boolean): void delayLeave?( el: HostElement, earlyRemove: () => void, @@ -412,7 +412,7 @@ export function resolveTransitionHooks( el[enterCbKey](true /* cancelled */) } if (state.isUnmounting) { - return remove() + return remove(state.isUnmounting) } callHook(onBeforeLeave, [el]) let called = false diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts index 7c3c75a6fe7..72279abec8f 100644 --- a/packages/runtime-core/src/components/Suspense.ts +++ b/packages/runtime-core/src/components/Suspense.ts @@ -542,7 +542,7 @@ function createSuspenseBoundary( pendingBranch!.transition && pendingBranch!.transition.mode === 'out-in' if (delayEnter) { - activeBranch!.transition!.afterLeave = () => { + activeBranch!.transition!.afterLeave = isUnmounted => { if (pendingId === suspense.pendingId) { move( pendingBranch!, @@ -550,7 +550,7 @@ function createSuspenseBoundary( anchor === initialAnchor ? next(activeBranch!) : anchor, MoveType.ENTER, ) - queuePostFlushCb(effects) + if (!isUnmounted) queuePostFlushCb(effects) } } } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 542341b13e8..42cc934f2fe 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -2221,10 +2221,10 @@ function baseCreateRenderer( return } - const performRemove = () => { + const performRemove = (isUnmounted?: boolean) => { hostRemove(el!) if (transition && !transition.persisted && transition.afterLeave) { - transition.afterLeave() + transition.afterLeave(isUnmounted) } } From 2d40759a357f3b5a764e75035bbdcd4757bf69d6 Mon Sep 17 00:00:00 2001 From: linzhe Date: Mon, 3 Jun 2024 13:17:40 +0800 Subject: [PATCH 2/6] test: add test --- .../runtime-dom/__tests__/createApp.spec.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/runtime-dom/__tests__/createApp.spec.ts b/packages/runtime-dom/__tests__/createApp.spec.ts index 9a8d05df2df..29ce670e290 100644 --- a/packages/runtime-dom/__tests__/createApp.spec.ts +++ b/packages/runtime-dom/__tests__/createApp.spec.ts @@ -1,4 +1,5 @@ import { createApp, h } from '../src' +import { defineComponent, onMounted, shallowRef } from 'vue' describe('createApp for dom', () => { // #2926 @@ -39,4 +40,46 @@ describe('createApp for dom', () => { // ensure no mutation happened to Root object expect(originalObj).toMatchObject(Root) }) + test('When the app is unmounted, the onMounted of suspense in Transition should not be called', async () => { + const onPage2Mounted = vi.fn() + const Page1 = defineComponent({ + name: 'Page1', + setup() { + return () => h('div', null, 'page1') + }, + }) + const Page2 = defineComponent({ + name: 'Page2', + setup() { + onMounted(onPage2Mounted) + return () => h('div', null, 'page2') + }, + }) + const Component = shallowRef(Page1) + const App = defineComponent({ + setup() { + return { + Component, + } + }, + template: ` +
+ +
+ `, + }) + const app = createApp(App) + app.mount(document.createElement('div')) + Component.value = Page2 + app.unmount() + expect(onPage2Mounted).toHaveBeenCalledTimes(0) + }) }) From e9a1b65a2549416cd4b6a4806486099ed835c5a7 Mon Sep 17 00:00:00 2001 From: linzhe Date: Mon, 3 Jun 2024 15:09:17 +0800 Subject: [PATCH 3/6] fix: When keepalive is unMounted, the afterLeave of the transition should only be executed once --- packages/runtime-core/src/components/BaseTransition.ts | 6 +++--- packages/runtime-core/src/components/Suspense.ts | 5 +++-- packages/runtime-core/src/renderer.ts | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index 23829afcbd5..070418a19a0 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -60,10 +60,10 @@ export interface TransitionHooks { persisted: boolean beforeEnter(el: HostElement): void enter(el: HostElement): void - leave(el: HostElement, remove: (isUnmounting?: boolean) => void): void + leave(el: HostElement, remove: () => void): void clone(vnode: VNode): TransitionHooks // optional - afterLeave?(isUnmounting?: boolean): void + afterLeave?(): void delayLeave?( el: HostElement, earlyRemove: () => void, @@ -412,7 +412,7 @@ export function resolveTransitionHooks( el[enterCbKey](true /* cancelled */) } if (state.isUnmounting) { - return remove(state.isUnmounting) + return remove() } callHook(onBeforeLeave, [el]) let called = false diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts index 72279abec8f..2584ac8814a 100644 --- a/packages/runtime-core/src/components/Suspense.ts +++ b/packages/runtime-core/src/components/Suspense.ts @@ -542,7 +542,7 @@ function createSuspenseBoundary( pendingBranch!.transition && pendingBranch!.transition.mode === 'out-in' if (delayEnter) { - activeBranch!.transition!.afterLeave = isUnmounted => { + activeBranch!.transition!.afterLeave = () => { if (pendingId === suspense.pendingId) { move( pendingBranch!, @@ -550,8 +550,9 @@ function createSuspenseBoundary( anchor === initialAnchor ? next(activeBranch!) : anchor, MoveType.ENTER, ) - if (!isUnmounted) queuePostFlushCb(effects) + queuePostFlushCb(effects) } + activeBranch!.transition!.afterLeave = undefined } } // unmount current active tree diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 42cc934f2fe..542341b13e8 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -2221,10 +2221,10 @@ function baseCreateRenderer( return } - const performRemove = (isUnmounted?: boolean) => { + const performRemove = () => { hostRemove(el!) if (transition && !transition.persisted && transition.afterLeave) { - transition.afterLeave(isUnmounted) + transition.afterLeave() } } From db2930242ca77ef88f01bb245354bcbd9fa3e7b0 Mon Sep 17 00:00:00 2001 From: linzhe Date: Fri, 2 Aug 2024 23:47:13 +0800 Subject: [PATCH 4/6] chore: update test --- .../runtime-dom/__tests__/createApp.spec.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/runtime-dom/__tests__/createApp.spec.ts b/packages/runtime-dom/__tests__/createApp.spec.ts index 29ce670e290..040adbadec2 100644 --- a/packages/runtime-dom/__tests__/createApp.spec.ts +++ b/packages/runtime-dom/__tests__/createApp.spec.ts @@ -1,4 +1,4 @@ -import { createApp, h } from '../src' +import { createApp, h, ref } from '../src' import { defineComponent, onMounted, shallowRef } from 'vue' describe('createApp for dom', () => { @@ -42,6 +42,7 @@ describe('createApp for dom', () => { }) test('When the app is unmounted, the onMounted of suspense in Transition should not be called', async () => { const onPage2Mounted = vi.fn() + let page1Comp: any const Page1 = defineComponent({ name: 'Page1', setup() { @@ -56,10 +57,12 @@ describe('createApp for dom', () => { }, }) const Component = shallowRef(Page1) + const page = ref(null) const App = defineComponent({ setup() { return { Component, + page, } }, template: ` @@ -68,7 +71,7 @@ describe('createApp for dom', () => { - + @@ -78,8 +81,20 @@ describe('createApp for dom', () => { }) const app = createApp(App) app.mount(document.createElement('div')) + await new Promise(resolve => { + setTimeout(resolve, 500) + }) + page1Comp = page.value Component.value = Page2 + await new Promise(resolve => { + setTimeout(resolve, 500) + }) + expect(onPage2Mounted).toHaveBeenCalledTimes(1) app.unmount() - expect(onPage2Mounted).toHaveBeenCalledTimes(0) + await new Promise(resolve => { + setTimeout(resolve, 500) + }) + expect(onPage2Mounted).toHaveBeenCalledTimes(1) + expect(page1Comp._.vnode.transition.afterLeave).toBe(undefined) }) }) From 7e68aeb39f5997f2c55dffe619961ee1d9759880 Mon Sep 17 00:00:00 2001 From: edison Date: Wed, 30 Oct 2024 17:23:52 +0800 Subject: [PATCH 5/6] Update createApp.spec.ts --- packages/runtime-dom/__tests__/createApp.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/runtime-dom/__tests__/createApp.spec.ts b/packages/runtime-dom/__tests__/createApp.spec.ts index 040adbadec2..b1ed6ae826d 100644 --- a/packages/runtime-dom/__tests__/createApp.spec.ts +++ b/packages/runtime-dom/__tests__/createApp.spec.ts @@ -40,6 +40,7 @@ describe('createApp for dom', () => { // ensure no mutation happened to Root object expect(originalObj).toMatchObject(Root) }) + test('When the app is unmounted, the onMounted of suspense in Transition should not be called', async () => { const onPage2Mounted = vi.fn() let page1Comp: any From 9f8be34bdabc902c1df1ff6076e8c01e49f9a75b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 09:24:48 +0000 Subject: [PATCH 6/6] [autofix.ci] apply automated fixes --- packages/runtime-dom/__tests__/createApp.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-dom/__tests__/createApp.spec.ts b/packages/runtime-dom/__tests__/createApp.spec.ts index b1ed6ae826d..7a865908847 100644 --- a/packages/runtime-dom/__tests__/createApp.spec.ts +++ b/packages/runtime-dom/__tests__/createApp.spec.ts @@ -40,7 +40,7 @@ describe('createApp for dom', () => { // ensure no mutation happened to Root object expect(originalObj).toMatchObject(Root) }) - + test('When the app is unmounted, the onMounted of suspense in Transition should not be called', async () => { const onPage2Mounted = vi.fn() let page1Comp: any