fix(keep-alive): do not invoke onVnodeBeforeUnmount if is KeepAlive component (#1079)
This commit is contained in:
parent
2e0373bb7a
commit
239270c38a
@ -7,7 +7,14 @@ import {
|
||||
KeepAlive,
|
||||
serializeInner,
|
||||
nextTick,
|
||||
ComponentOptions
|
||||
ComponentOptions,
|
||||
markRaw,
|
||||
inject,
|
||||
defineComponent,
|
||||
ComponentPublicInstance,
|
||||
Ref,
|
||||
cloneVNode,
|
||||
provide
|
||||
} from '@vue/runtime-test'
|
||||
import { KeepAliveProps } from '../../src/components/KeepAlive'
|
||||
|
||||
@ -559,4 +566,91 @@ describe('KeepAlive', () => {
|
||||
expect(serializeInner(root)).toBe(`1`)
|
||||
})
|
||||
})
|
||||
|
||||
it('should not call onVnodeUnmounted', async () => {
|
||||
const Foo = markRaw({
|
||||
name: 'Foo',
|
||||
render() {
|
||||
return h('Foo')
|
||||
}
|
||||
})
|
||||
const Bar = markRaw({
|
||||
name: 'Bar',
|
||||
render() {
|
||||
return h('Bar')
|
||||
}
|
||||
})
|
||||
|
||||
const spyMounted = jest.fn()
|
||||
const spyUnmounted = jest.fn()
|
||||
|
||||
const RouterView = defineComponent({
|
||||
setup(_, { slots }) {
|
||||
const Component = inject<Ref<ComponentPublicInstance>>('component')
|
||||
const refView = ref()
|
||||
|
||||
let componentProps = {
|
||||
ref: refView,
|
||||
onVnodeMounted() {
|
||||
spyMounted()
|
||||
},
|
||||
onVnodeUnmounted() {
|
||||
spyUnmounted()
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
const child: any = slots.default!({
|
||||
Component: Component!.value
|
||||
})[0]
|
||||
|
||||
const innerChild = child.children[0]
|
||||
child.children[0] = cloneVNode(innerChild, componentProps)
|
||||
return child
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let toggle: () => void = () => {}
|
||||
|
||||
const App = defineComponent({
|
||||
setup() {
|
||||
const component = ref(Foo)
|
||||
|
||||
provide('component', component)
|
||||
|
||||
toggle = () => {
|
||||
component.value = component.value === Foo ? Bar : Foo
|
||||
}
|
||||
return {
|
||||
component,
|
||||
toggle
|
||||
}
|
||||
},
|
||||
render() {
|
||||
return h(RouterView, null, {
|
||||
default: ({ Component }: any) => h(KeepAlive, null, [h(Component)])
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
render(h(App), root)
|
||||
await nextTick()
|
||||
expect(spyMounted).toHaveBeenCalledTimes(1)
|
||||
expect(spyUnmounted).toHaveBeenCalledTimes(0)
|
||||
|
||||
toggle()
|
||||
await nextTick()
|
||||
|
||||
expect(spyMounted).toHaveBeenCalledTimes(2)
|
||||
expect(spyUnmounted).toHaveBeenCalledTimes(0)
|
||||
|
||||
toggle()
|
||||
await nextTick()
|
||||
render(null, root)
|
||||
await nextTick()
|
||||
|
||||
expect(spyMounted).toHaveBeenCalledTimes(2)
|
||||
expect(spyUnmounted).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
@ -1713,6 +1713,7 @@ function baseCreateRenderer(
|
||||
) => {
|
||||
const { props, ref, children, dynamicChildren, shapeFlag, dirs } = vnode
|
||||
const shouldInvokeDirs = shapeFlag & ShapeFlags.ELEMENT && dirs
|
||||
const shouldKeepAlive = shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
|
||||
let vnodeHook: VNodeHook | undefined | null
|
||||
|
||||
// unset ref
|
||||
@ -1720,12 +1721,12 @@ function baseCreateRenderer(
|
||||
setRef(ref, null, parentComponent, null)
|
||||
}
|
||||
|
||||
if ((vnodeHook = props && props.onVnodeBeforeUnmount)) {
|
||||
if ((vnodeHook = props && props.onVnodeBeforeUnmount) && !shouldKeepAlive) {
|
||||
invokeVNodeHook(vnodeHook, parentComponent, vnode)
|
||||
}
|
||||
|
||||
if (shapeFlag & ShapeFlags.COMPONENT) {
|
||||
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
|
||||
if (shouldKeepAlive) {
|
||||
;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
|
||||
} else {
|
||||
unmountComponent(vnode.component!, parentSuspense, doRemove)
|
||||
@ -1757,7 +1758,10 @@ function baseCreateRenderer(
|
||||
}
|
||||
}
|
||||
|
||||
if ((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) {
|
||||
if (
|
||||
((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) &&
|
||||
!shouldKeepAlive
|
||||
) {
|
||||
queuePostRenderEffect(() => {
|
||||
vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)
|
||||
shouldInvokeDirs &&
|
||||
|
Loading…
Reference in New Issue
Block a user