Skip to content

Commit

Permalink
fix(runtime-core): fix activated hook when using async component with…
Browse files Browse the repository at this point in the history
… KeepAlive (#5459)

fix #5095
fix #5651
  • Loading branch information
edison1105 authored May 12, 2022
1 parent d4fcfdd commit f1d1cdb
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
38 changes: 37 additions & 1 deletion packages/runtime-core/__tests__/apiAsyncComponent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -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)
})

})
8 changes: 6 additions & 2 deletions packages/runtime-core/src/apiAsyncComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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
}

0 comments on commit f1d1cdb

Please sign in to comment.