fix(keep-alive): do not invoke onVnodeBeforeUnmount if is KeepAlive component (#1079)

This commit is contained in:
Carlos Rodrigues 2020-04-30 19:52:03 +01:00 committed by GitHub
parent 2e0373bb7a
commit 239270c38a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 4 deletions

View File

@ -7,7 +7,14 @@ import {
KeepAlive, KeepAlive,
serializeInner, serializeInner,
nextTick, nextTick,
ComponentOptions ComponentOptions,
markRaw,
inject,
defineComponent,
ComponentPublicInstance,
Ref,
cloneVNode,
provide
} from '@vue/runtime-test' } from '@vue/runtime-test'
import { KeepAliveProps } from '../../src/components/KeepAlive' import { KeepAliveProps } from '../../src/components/KeepAlive'
@ -559,4 +566,91 @@ describe('KeepAlive', () => {
expect(serializeInner(root)).toBe(`1`) 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)
})
}) })

View File

@ -1713,6 +1713,7 @@ function baseCreateRenderer(
) => { ) => {
const { props, ref, children, dynamicChildren, shapeFlag, dirs } = vnode const { props, ref, children, dynamicChildren, shapeFlag, dirs } = vnode
const shouldInvokeDirs = shapeFlag & ShapeFlags.ELEMENT && dirs const shouldInvokeDirs = shapeFlag & ShapeFlags.ELEMENT && dirs
const shouldKeepAlive = shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
let vnodeHook: VNodeHook | undefined | null let vnodeHook: VNodeHook | undefined | null
// unset ref // unset ref
@ -1720,12 +1721,12 @@ function baseCreateRenderer(
setRef(ref, null, parentComponent, null) setRef(ref, null, parentComponent, null)
} }
if ((vnodeHook = props && props.onVnodeBeforeUnmount)) { if ((vnodeHook = props && props.onVnodeBeforeUnmount) && !shouldKeepAlive) {
invokeVNodeHook(vnodeHook, parentComponent, vnode) invokeVNodeHook(vnodeHook, parentComponent, vnode)
} }
if (shapeFlag & ShapeFlags.COMPONENT) { if (shapeFlag & ShapeFlags.COMPONENT) {
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) { if (shouldKeepAlive) {
;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode) ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
} else { } else {
unmountComponent(vnode.component!, parentSuspense, doRemove) 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(() => { queuePostRenderEffect(() => {
vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode) vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)
shouldInvokeDirs && shouldInvokeDirs &&