fix(keep-alive): fix unmounting late-included components

fix #3648
based on #3650
This commit is contained in:
Evan You 2022-05-12 11:52:54 +08:00
parent 20ed16f68c
commit da49c863a2
2 changed files with 77 additions and 2 deletions

View File

@ -18,7 +18,12 @@ import {
defineAsyncComponent,
Component,
createApp,
onActivated
onActivated,
onUnmounted,
onMounted,
reactive,
shallowRef,
onDeactivated
} from '@vue/runtime-test'
import { KeepAliveProps } from '../../src/components/KeepAlive'
@ -903,4 +908,73 @@ describe('KeepAlive', () => {
await nextTick()
expect(handler).toHaveBeenCalledWith(err, {}, 'activated hook')
})
// #3648
test('should avoid unmount later included components', async () => {
const unmountedA = jest.fn()
const mountedA = jest.fn()
const activatedA = jest.fn()
const deactivatedA = jest.fn()
const unmountedB = jest.fn()
const mountedB = jest.fn()
const A = {
name: 'A',
setup() {
onMounted(mountedA)
onUnmounted(unmountedA)
onActivated(activatedA)
onDeactivated(deactivatedA)
return () => 'A'
}
}
const B = {
name: 'B',
setup() {
onMounted(mountedB)
onUnmounted(unmountedB)
return () => 'B'
}
}
const include = reactive<string[]>([])
const current = shallowRef(A)
const app = createApp({
setup() {
return () => {
return [
h(
KeepAlive,
{
include
},
h(current.value)
)
]
}
}
})
app.mount(root)
expect(serializeInner(root)).toBe(`A`)
expect(mountedA).toHaveBeenCalledTimes(1)
expect(unmountedA).toHaveBeenCalledTimes(0)
expect(activatedA).toHaveBeenCalledTimes(0)
expect(deactivatedA).toHaveBeenCalledTimes(0)
expect(mountedB).toHaveBeenCalledTimes(0)
expect(unmountedB).toHaveBeenCalledTimes(0)
include.push('A') // cache A
await nextTick()
current.value = B // toggle to B
await nextTick()
expect(serializeInner(root)).toBe(`B`)
expect(mountedA).toHaveBeenCalledTimes(1)
expect(unmountedA).toHaveBeenCalledTimes(0)
expect(activatedA).toHaveBeenCalledTimes(0)
expect(deactivatedA).toHaveBeenCalledTimes(1)
expect(mountedB).toHaveBeenCalledTimes(1)
expect(unmountedB).toHaveBeenCalledTimes(0)
})
})

View File

@ -42,6 +42,7 @@ import { setTransitionHooks } from './BaseTransition'
import { ComponentRenderContext } from '../componentPublicInstance'
import { devtoolsComponentAdded } from '../devtools'
import { isAsyncWrapper } from '../apiAsyncComponent'
import { isSuspense } from './Suspense'
type MatchPattern = string | RegExp | (string | RegExp)[]
@ -323,7 +324,7 @@ const KeepAliveImpl: ComponentOptions = {
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
current = vnode
return rawVNode
return isSuspense(rawVNode.type) ? rawVNode : vnode
}
}
}