diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts index f75bb039c4e..8eee2c05e6b 100644 --- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts +++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts @@ -165,6 +165,36 @@ describe('KeepAlive', () => { assertHookCalls(two, [1, 1, 2, 2, 0]) }) + // #1742 + test('should call lifecycle hooks on nested components when root component no hooks', async () => { + const two = { + name: 'two', + data: () => ({ msg: 'two' }), + render(this: any) { + return h('div', this.msg) + }, + activated: jest.fn() + } + const one = { + name: 'one', + data: () => ({ msg: 'one' }), + render(this: any) { + return h(two) + } + } + + const toggle = ref(true) + const App = { + render() { + return h(KeepAlive, () => (toggle.value ? h(one) : null)) + } + } + render(h(App), root) + + expect(serializeInner(root)).toBe(`
two
`) + expect(two.activated).toHaveBeenCalledTimes(1) + }) + test('should call correct hooks for nested keep-alive', async () => { const toggle2 = ref(true) one.render = () => h(KeepAlive, () => (toggle2.value ? h(two) : null)) diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index ed832253182..5bdc0aa1fff 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -1264,7 +1264,7 @@ function baseCreateRenderer( if (!instance.isMounted) { let vnodeHook: VNodeHook | null | undefined const { el, props } = initialVNode - const { bm, m, a, parent } = instance + const { bm, m, parent } = instance if (__DEV__) { startMeasure(instance, `render`) } @@ -1323,6 +1323,9 @@ function baseCreateRenderer( }, parentSuspense) } // 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 + const { a } = instance if ( a && initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE