From 8fecc3006aa2b86f65a0c02bebcc31ac23ab2362 Mon Sep 17 00:00:00 2001 From: Rairn <958414905@qq.com> Date: Wed, 7 Dec 2022 16:08:34 +0800 Subject: [PATCH 1/3] fix(keep-alive): invoke initial activated hook for async components's child component (#7276) --- .../__tests__/components/KeepAlive.spec.ts | 36 +++++++++++++++++++ .../runtime-core/src/components/KeepAlive.ts | 10 +++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts index 344fba156c3..dd1c14f4be5 100644 --- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts +++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts @@ -883,6 +883,42 @@ describe('KeepAlive', () => { expect(serializeInner(root)).toBe('
1
') }) + // #7276 + test('should invoke onActivated of child on initial mount', async () => { + let parentCount = 0 + let childCount = 0 + const Child = defineComponent({ + name: 'Child', + setup() { + onActivated(() => { + childCount++ + }) + return () => 'child' + } + }) + const Parent = defineComponent({ + setup() { + onActivated(() => { + parentCount++ + }) + return () => h(Child) + } + }) + const AsyncComp = defineAsyncComponent(() => Promise.resolve(Parent)) + + const App = { + render: () => { + return h(KeepAlive, null, () => h(AsyncComp)) + } + } + + render(h(App), root) + await timeout() + expect(serializeInner(root)).toBe('child') + expect(parentCount).toBe(1) + expect(childCount).toBe(1) + }) + // #4976 test('handle error in async onActivated', async () => { const err = new Error('foo') diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index d5813f90e09..3bc58edfe6a 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -402,10 +402,18 @@ function registerKeepAliveHook( // arrays. if (target) { let current = target.parent + let child = target while (current && current.parent) { if (isKeepAlive(current.parent.vnode)) { - injectToKeepAliveRoot(wrappedHook, type, target, current) + injectToKeepAliveRoot( + wrappedHook, + type, + target, + // #7276 + isAsyncWrapper(current) ? child : current + ) } + child = current current = current.parent } } From 31929a20047e94a7c5c2c06da98cbc38041340e2 Mon Sep 17 00:00:00 2001 From: Rairn <958414905@qq.com> Date: Wed, 7 Dec 2022 17:34:30 +0800 Subject: [PATCH 2/3] fix: avoid other bugs --- .../__tests__/components/KeepAlive.spec.ts | 10 +++++++++- packages/runtime-core/src/components/KeepAlive.ts | 10 +--------- packages/runtime-core/src/renderer.ts | 15 +++++++++++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts index dd1c14f4be5..a11b24e2234 100644 --- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts +++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts @@ -887,6 +887,7 @@ describe('KeepAlive', () => { test('should invoke onActivated of child on initial mount', async () => { let parentCount = 0 let childCount = 0 + const toggle = ref(true) const Child = defineComponent({ name: 'Child', setup() { @@ -908,7 +909,7 @@ describe('KeepAlive', () => { const App = { render: () => { - return h(KeepAlive, null, () => h(AsyncComp)) + return h(KeepAlive, null, () => (toggle.value ? h(AsyncComp) : null)) } } @@ -917,6 +918,13 @@ describe('KeepAlive', () => { expect(serializeInner(root)).toBe('child') expect(parentCount).toBe(1) expect(childCount).toBe(1) + + toggle.value = false + await timeout() + toggle.value = true + await timeout() + expect(parentCount).toBe(2) + expect(childCount).toBe(2) }) // #4976 diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index 3bc58edfe6a..d5813f90e09 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -402,18 +402,10 @@ function registerKeepAliveHook( // arrays. if (target) { let current = target.parent - let child = target while (current && current.parent) { if (isKeepAlive(current.parent.vnode)) { - injectToKeepAliveRoot( - wrappedHook, - type, - target, - // #7276 - isAsyncWrapper(current) ? child : current - ) + injectToKeepAliveRoot(wrappedHook, type, target, current) } - child = current current = current.parent } } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 413355508b9..fd25e9fd992 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1413,16 +1413,23 @@ function baseCreateRenderer( ) } + const parentIsAsyncWrapperAndShouldKeepAlive = + parent && + isAsyncWrapper(parent.vnode) && + parent.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE // activated hook for keep-alive roots. // #1742 activated hook must be accessed after first render // since the hook may be injected by a child keep-alive if ( initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE || - (parent && - isAsyncWrapper(parent.vnode) && - parent.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) + parentIsAsyncWrapperAndShouldKeepAlive ) { - instance.a && queuePostRenderEffect(instance.a, parentSuspense) + if (parentIsAsyncWrapperAndShouldKeepAlive) { + // #7276 - parent.a contains all the hooks of the descendants + parent.a && queuePostRenderEffect(parent.a, parentSuspense) + } else { + instance.a && queuePostRenderEffect(instance.a, parentSuspense) + } if ( __COMPAT__ && isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance) From 2b4c2ae01c89b69882897804eafc078bd15f1885 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:09:56 +0000 Subject: [PATCH 3/3] [autofix.ci] apply automated fixes --- .../runtime-core/__tests__/components/KeepAlive.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts index f7f8ebb19bc..2dcf08df070 100644 --- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts +++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts @@ -894,7 +894,7 @@ describe('KeepAlive', () => { childCount++ }) return () => 'child' - } + }, }) const Parent = defineComponent({ setup() { @@ -902,14 +902,14 @@ describe('KeepAlive', () => { parentCount++ }) return () => h(Child) - } + }, }) const AsyncComp = defineAsyncComponent(() => Promise.resolve(Parent)) const App = { render: () => { return h(KeepAlive, null, () => (toggle.value ? h(AsyncComp) : null)) - } + }, } render(h(App), root)