fix(keep-alive): fix unmounting late-included components
fix #3648 based on #3650
This commit is contained in:
parent
20ed16f68c
commit
da49c863a2
@ -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)
|
||||
})
|
||||
})
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user