From 1c5d833a76ea4290864f40a5cd0b32f96e24793c Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 9 Apr 2025 21:19:29 +0800 Subject: [PATCH] wip: refactor --- .../__tests__/components/KeepAlive.spec.ts | 76 +++++++++---------- packages/runtime-vapor/src/block.ts | 6 +- packages/runtime-vapor/src/component.ts | 6 ++ .../runtime-vapor/src/components/KeepAlive.ts | 3 + 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts b/packages/runtime-vapor/__tests__/components/KeepAlive.spec.ts index ea1ee8527a..4cd8727f00 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]) - - // // 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 - - // 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 = 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 = 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 + + 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 = 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 }) }) diff --git a/packages/runtime-vapor/src/block.ts b/packages/runtime-vapor/src/block.ts index c93e94612a..c9d81986b4 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 26a1226477..4ad5e7f026 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 6b7192c6bd..f40a508a57 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 -- 2.47.2