diff --git a/packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts b/packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts index ea1ee8527..4cd8727f0 100644 --- a/packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts +++ b/packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts @@ -365,7 +365,7 @@ describe('VaporKeepAlive', () => { expect(spy).toHaveBeenCalledTimes(1) }) - test.todo('should call correct hooks for nested keep-alive', async () => { + test('should call correct hooks for nested keep-alive', async () => { const toggle2 = ref(true) const one = defineVaporComponent({ name: 'one', @@ -431,42 +431,42 @@ describe('VaporKeepAlive', () => { // the activated hook of two is not called assertHookCalls(twoHooks, [1, 1, 3, 2, 0]) - // toggle1.value = false - // await nextTick() - // expect(html()).toBe(``) - // assertHookCalls(oneHooks, [1, 1, 2, 2, 0]) - // assertHookCalls(twoHooks, [1, 1, 3, 3, 0]) + toggle1.value = false + await nextTick() + expect(html()).toBe(``) + assertHookCalls(oneHooks, [1, 1, 2, 2, 0]) + assertHookCalls(twoHooks, [1, 1, 3, 3, 0]) - // // toggle nested instance when parent is deactivated - // toggle2.value = false - // await nextTick() - // expect(html()).toBe(``) - // assertHookCalls(oneHooks, [1, 1, 2, 2, 0]) - // // assertHookCalls(twoHooks, [1, 1, 3, 3, 0]) // should not be affected + // toggle nested instance when parent is deactivated + toggle2.value = false + await nextTick() + expect(html()).toBe(``) + assertHookCalls(oneHooks, [1, 1, 2, 2, 0]) + assertHookCalls(twoHooks, [1, 1, 3, 3, 0]) // should not be affected - // toggle2.value = true - // await nextTick() - // expect(html()).toBe(``) - // assertHookCalls(oneHooks, [1, 1, 2, 2, 0]) - // // assertHookCalls(twoHooks, [1, 1, 3, 3, 0]) // should not be affected + toggle2.value = true + await nextTick() + expect(html()).toBe(``) + assertHookCalls(oneHooks, [1, 1, 2, 2, 0]) + assertHookCalls(twoHooks, [1, 1, 3, 3, 0]) // should not be affected - // toggle1.value = true - // await nextTick() - // expect(html()).toBe(`
two
`) - // assertHookCalls(oneHooks, [1, 1, 3, 2, 0]) - // // assertHookCalls(twoHooks, [1, 1, 4, 3, 0]) + toggle1.value = true + await nextTick() + expect(html()).toBe(`
two
`) + assertHookCalls(oneHooks, [1, 1, 3, 2, 0]) + assertHookCalls(twoHooks, [1, 1, 4, 3, 0]) - // toggle1.value = false - // toggle2.value = false - // await nextTick() - // expect(html()).toBe(``) - // assertHookCalls(oneHooks, [1, 1, 3, 3, 0]) - // // assertHookCalls(twoHooks, [1, 1, 4, 4, 0]) + toggle1.value = false + toggle2.value = false + await nextTick() + expect(html()).toBe(``) + assertHookCalls(oneHooks, [1, 1, 3, 3, 0]) + assertHookCalls(twoHooks, [1, 1, 4, 4, 0]) - // toggle1.value = true - // await nextTick() - // expect(html()).toBe(``) - // assertHookCalls(oneHooks, [1, 1, 4, 3, 0]) - // // assertHookCalls(twoHooks, [1, 1, 4, 4, 0]) // should remain inactive + toggle1.value = true + await nextTick() + expect(html()).toBe(``) + assertHookCalls(oneHooks, [1, 1, 4, 3, 0]) + assertHookCalls(twoHooks, [1, 1, 4, 4, 0]) // should remain inactive }) }) diff --git a/packages/runtime-vapor/src/block.ts b/packages/runtime-vapor/src/block.ts index c93e94612..c9d81986b 100644 --- a/packages/runtime-vapor/src/block.ts +++ b/packages/runtime-vapor/src/block.ts @@ -60,8 +60,10 @@ export class DynamicFragment extends VaporFragment { ;(instance as KeepAliveInstance).process( this.nodes as VaporComponentInstance, ) + unmountComponent(this.nodes as VaporComponentInstance) + } else { + this.scope.stop() } - this.scope.stop() parent && remove(this.nodes, parent) } @@ -128,7 +130,7 @@ export function insert( parent.insertBefore(block, anchor) } } else if (isVaporComponent(block)) { - if (block.isMounted) { + if (block.isMounted && !block.isDeactivated) { insert(block.block!, parent, anchor) } else { mountComponent(block, parent, anchor) diff --git a/packages/runtime-vapor/src/component.ts b/packages/runtime-vapor/src/component.ts index 26a122647..4ad5e7f02 100644 --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@ -15,6 +15,7 @@ import { currentInstance, endMeasure, expose, + isKeepAlive, nextUid, popWarningContext, pushWarningContext, @@ -151,6 +152,11 @@ export function createComponent( locateHydrationNode() } + if (currentInstance && isKeepAlive(currentInstance)) { + const cache = (currentInstance as KeepAliveInstance).getCache(component) + if (cache) return cache + } + // vdom interop enabled and component is not an explicit vapor component if (appContext.vapor && !component.__vapor) { const frag = appContext.vapor.vdomMount( diff --git a/packages/runtime-vapor/src/components/KeepAlive.ts b/packages/runtime-vapor/src/components/KeepAlive.ts index 6b7192c6b..f40a508a5 100644 --- a/packages/runtime-vapor/src/components/KeepAlive.ts +++ b/packages/runtime-vapor/src/components/KeepAlive.ts @@ -31,6 +31,7 @@ export interface KeepAliveInstance extends VaporComponentInstance { ) => void deactivate: (instance: VaporComponentInstance) => void process: (instance: VaporComponentInstance) => void + getCache: (comp: VaporComponent) => VaporComponentInstance | undefined } type CacheKey = PropertyKey | VaporComponent @@ -103,6 +104,8 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({ }) }) + keepAliveInstance.getCache = (comp: VaporComponent) => cache.get(comp) + keepAliveInstance.process = (instance: VaporComponentInstance) => { if (cache.has(instance.type)) { instance.shapeFlag! |= ShapeFlags.COMPONENT_KEPT_ALIVE