diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts index 6d3f6a9b8b6..2dcf08df070 100644 --- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts +++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts @@ -882,6 +882,50 @@ 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 toggle = ref(true) + 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, () => (toggle.value ? h(AsyncComp) : null)) + }, + } + + render(h(App), root) + await timeout() + 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 test('handle error in async onActivated', async () => { const err = new Error('foo') diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 49ef212039b..9eb45935756 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1381,16 +1381,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)