Skip to content

Commit f1d1cdb

Browse files
authored
fix(runtime-core): fix activated hook when using async component with KeepAlive (#5459)
fix #5095 fix #5651
1 parent d4fcfdd commit f1d1cdb

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

packages/runtime-core/__tests__/apiAsyncComponent.spec.ts

+37-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import {
44
Component,
55
ref,
66
nextTick,
7-
Suspense
7+
Suspense,
8+
KeepAlive
89
} from '../src'
910
import { createApp, nodeOps, serializeInner } from '@vue/runtime-test'
11+
import { onActivated } from '../src/components/KeepAlive'
1012

1113
const timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))
1214

@@ -799,4 +801,38 @@ describe('api: defineAsyncComponent', () => {
799801
expect(vnodeHooks.onVnodeBeforeUnmount).toHaveBeenCalledTimes(1)
800802
expect(vnodeHooks.onVnodeUnmounted).toHaveBeenCalledTimes(1)
801803
})
804+
805+
test('with keepalive', async () => {
806+
const spy = jest.fn()
807+
let resolve: (comp: Component) => void
808+
809+
const Foo = defineAsyncComponent(
810+
() =>
811+
new Promise(r => {
812+
resolve = r as any
813+
})
814+
)
815+
816+
const root = nodeOps.createElement('div')
817+
const app = createApp({
818+
render: () => h(KeepAlive, [h(Foo)])
819+
})
820+
821+
app.mount(root)
822+
await nextTick()
823+
824+
resolve!({
825+
setup() {
826+
onActivated(() => {
827+
spy()
828+
})
829+
return () => 'resolved'
830+
}
831+
})
832+
833+
await timeout()
834+
expect(serializeInner(root)).toBe('resolved')
835+
expect(spy).toBeCalledTimes(1)
836+
})
837+
802838
})

packages/runtime-core/src/apiAsyncComponent.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
isInSSRComponentSetup,
77
ComponentOptions
88
} from './component'
9-
import { isFunction, isObject } from '@vue/shared'
9+
import { isFunction, isObject, ShapeFlags } from '@vue/shared'
1010
import { ComponentPublicInstance } from './componentPublicInstance'
1111
import { createVNode, VNode } from './vnode'
1212
import { defineComponent } from './apiDefineComponent'
@@ -211,10 +211,14 @@ export function defineAsyncComponent<
211211

212212
function createInnerComp(
213213
comp: ConcreteComponent,
214-
{ vnode: { ref, props, children } }: ComponentInternalInstance
214+
{ vnode: { ref, props, children }, parent }: ComponentInternalInstance
215215
) {
216216
const vnode = createVNode(comp, props, children)
217217
// ensure inner component inherits the async wrapper's ref owner
218218
vnode.ref = ref
219+
220+
if (parent && isKeepAlive(parent.vnode)) {
221+
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
222+
}
219223
return vnode
220224
}

0 commit comments

Comments
 (0)