Skip to content

Commit 20ed16f

Browse files
committed
fix(keep-alive): invoke initial activated hook for async components
revert #5459 fix #5095 fix #5651
1 parent 9d815d2 commit 20ed16f

File tree

3 files changed

+22
-12
lines changed

3 files changed

+22
-12
lines changed

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

+11-5
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ describe('api: defineAsyncComponent', () => {
802802
expect(vnodeHooks.onVnodeUnmounted).toHaveBeenCalledTimes(1)
803803
})
804804

805-
test('with keepalive', async () => {
805+
test('with KeepAlive', async () => {
806806
const spy = jest.fn()
807807
let resolve: (comp: Component) => void
808808

@@ -813,9 +813,12 @@ describe('api: defineAsyncComponent', () => {
813813
})
814814
)
815815

816+
const Bar = defineAsyncComponent(() => Promise.resolve(() => 'Bar'))
817+
818+
const toggle = ref(true)
816819
const root = nodeOps.createElement('div')
817820
const app = createApp({
818-
render: () => h(KeepAlive, [h(Foo)])
821+
render: () => h(KeepAlive, [toggle.value ? h(Foo) : h(Bar)])
819822
})
820823

821824
app.mount(root)
@@ -826,13 +829,16 @@ describe('api: defineAsyncComponent', () => {
826829
onActivated(() => {
827830
spy()
828831
})
829-
return () => 'resolved'
832+
return () => 'Foo'
830833
}
831834
})
832835

833836
await timeout()
834-
expect(serializeInner(root)).toBe('resolved')
837+
expect(serializeInner(root)).toBe('Foo')
835838
expect(spy).toBeCalledTimes(1)
836-
})
837839

840+
toggle.value = false
841+
await timeout()
842+
expect(serializeInner(root)).toBe('Bar')
843+
})
838844
})

packages/runtime-core/src/apiAsyncComponent.ts

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

212212
function createInnerComp(
213213
comp: ConcreteComponent,
214-
{ vnode: { ref, props, children }, parent }: ComponentInternalInstance
214+
{
215+
vnode: { ref, props, children, shapeFlag },
216+
parent
217+
}: ComponentInternalInstance
215218
) {
216219
const vnode = createVNode(comp, props, children)
217220
// ensure inner component inherits the async wrapper's ref owner
218221
vnode.ref = ref
219-
220-
if (parent && isKeepAlive(parent.vnode)) {
221-
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
222-
}
223222
return vnode
224223
}

packages/runtime-core/src/renderer.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,12 @@ function baseCreateRenderer(
14201420
// activated hook for keep-alive roots.
14211421
// #1742 activated hook must be accessed after first render
14221422
// since the hook may be injected by a child keep-alive
1423-
if (initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
1423+
if (
1424+
initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE ||
1425+
(parent &&
1426+
isAsyncWrapper(parent.vnode) &&
1427+
parent.vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE)
1428+
) {
14241429
instance.a && queuePostRenderEffect(instance.a, parentSuspense)
14251430
if (
14261431
__COMPAT__ &&

0 commit comments

Comments
 (0)