fix(runtime-core): fix activated hook when using async component with KeepAlive (#5459)

fix #5095
fix #5651
This commit is contained in:
edison 2022-05-12 08:19:11 +08:00 committed by GitHub
parent d4fcfddec6
commit f1d1cdbb69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 3 deletions

View File

@ -4,9 +4,11 @@ import {
Component,
ref,
nextTick,
Suspense
Suspense,
KeepAlive
} from '../src'
import { createApp, nodeOps, serializeInner } from '@vue/runtime-test'
import { onActivated } from '../src/components/KeepAlive'
const timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))
@ -799,4 +801,38 @@ describe('api: defineAsyncComponent', () => {
expect(vnodeHooks.onVnodeBeforeUnmount).toHaveBeenCalledTimes(1)
expect(vnodeHooks.onVnodeUnmounted).toHaveBeenCalledTimes(1)
})
test('with keepalive', async () => {
const spy = jest.fn()
let resolve: (comp: Component) => void
const Foo = defineAsyncComponent(
() =>
new Promise(r => {
resolve = r as any
})
)
const root = nodeOps.createElement('div')
const app = createApp({
render: () => h(KeepAlive, [h(Foo)])
})
app.mount(root)
await nextTick()
resolve!({
setup() {
onActivated(() => {
spy()
})
return () => 'resolved'
}
})
await timeout()
expect(serializeInner(root)).toBe('resolved')
expect(spy).toBeCalledTimes(1)
})
})

View File

@ -6,7 +6,7 @@ import {
isInSSRComponentSetup,
ComponentOptions
} from './component'
import { isFunction, isObject } from '@vue/shared'
import { isFunction, isObject, ShapeFlags } from '@vue/shared'
import { ComponentPublicInstance } from './componentPublicInstance'
import { createVNode, VNode } from './vnode'
import { defineComponent } from './apiDefineComponent'
@ -211,10 +211,14 @@ export function defineAsyncComponent<
function createInnerComp(
comp: ConcreteComponent,
{ vnode: { ref, props, children } }: ComponentInternalInstance
{ vnode: { ref, props, children }, parent }: ComponentInternalInstance
) {
const vnode = createVNode(comp, props, children)
// ensure inner component inherits the async wrapper's ref owner
vnode.ref = ref
if (parent && isKeepAlive(parent.vnode)) {
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
}
return vnode
}