queuePostRenderEffect,
MoveType,
RendererElement,
- RendererNode
+ RendererNode,
+ invokeVNodeHook
} from '../renderer'
import { setTransitionHooks } from './BaseTransition'
import { ComponentRenderContext } from '../componentProxy'
const storageContainer = createElement('div')
sharedContext.activate = (vnode, container, anchor, isSVG, optimized) => {
- const child = vnode.component!
+ const instance = vnode.component!
move(vnode, container, anchor, MoveType.ENTER, parentSuspense)
// in case props have changed
patch(
- child.vnode,
+ instance.vnode,
vnode,
container,
anchor,
optimized
)
queuePostRenderEffect(() => {
- child.isDeactivated = false
- if (child.a) {
- invokeArrayFns(child.a)
+ instance.isDeactivated = false
+ if (instance.a) {
+ invokeArrayFns(instance.a)
+ }
+ const vnodeHook = vnode.props && vnode.props.onVnodeMounted
+ if (vnodeHook) {
+ invokeVNodeHook(vnodeHook, instance.parent, vnode)
}
}, parentSuspense)
}
sharedContext.deactivate = (vnode: VNode) => {
+ const instance = vnode.component!
move(vnode, storageContainer, null, MoveType.LEAVE, parentSuspense)
queuePostRenderEffect(() => {
- const component = vnode.component!
- if (component.da) {
- invokeArrayFns(component.da)
+ if (instance.da) {
+ invokeArrayFns(instance.da)
+ }
+ const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted
+ if (vnodeHook) {
+ invokeVNodeHook(vnodeHook, instance.parent, vnode)
}
- component.isDeactivated = true
+ instance.isDeactivated = true
}, parentSuspense)
}
function unmount(vnode: VNode) {
// reset the shapeFlag so it can be properly unmounted
- vnode.shapeFlag = ShapeFlags.STATEFUL_COMPONENT
+ resetShapeFlag(vnode)
_unmount(vnode, instance, parentSuspense)
}
} else if (current) {
// current active instance should no longer be kept-alive.
// we can't unmount it now but it might be later, so reset its flag now.
- current.shapeFlag = ShapeFlags.STATEFUL_COMPONENT
+ resetShapeFlag(current)
}
cache.delete(key)
keys.delete(key)
)
onBeforeUnmount(() => {
- cache.forEach(unmount)
+ cache.forEach(cached => {
+ const { subTree, suspense } = instance
+ if (cached.type === subTree.type) {
+ // current instance will be unmounted as part of keep-alive's unmount
+ resetShapeFlag(subTree)
+ // but invoke its deactivated hook here
+ const da = subTree.component!.da
+ da && queuePostRenderEffect(da, suspense)
+ return
+ }
+ unmount(cached)
+ })
})
return () => {
(include && (!name || !matches(include, name))) ||
(exclude && name && matches(exclude, name))
) {
- return vnode
+ return (current = vnode)
}
const key = vnode.key == null ? comp : vnode.key
remove(keepAliveRoot[type]!, hook)
}, target)
}
+
+function resetShapeFlag(vnode: VNode) {
+ let shapeFlag = vnode.shapeFlag
+ if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
+ shapeFlag -= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
+ }
+ if (shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
+ shapeFlag -= ShapeFlags.COMPONENT_KEPT_ALIVE
+ }
+ vnode.shapeFlag = shapeFlag
+}
patchFlag,
dirs
} = vnode
- const shouldInvokeDirs = shapeFlag & ShapeFlags.ELEMENT && dirs
- const shouldKeepAlive = shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
- let vnodeHook: VNodeHook | undefined | null
-
// unset ref
if (ref != null && parentComponent) {
setRef(ref, null, parentComponent, null)
}
- if ((vnodeHook = props && props.onVnodeBeforeUnmount) && !shouldKeepAlive) {
+ if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
+ ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
+ return
+ }
+
+ const shouldInvokeDirs = shapeFlag & ShapeFlags.ELEMENT && dirs
+
+ let vnodeHook: VNodeHook | undefined | null
+ if ((vnodeHook = props && props.onVnodeBeforeUnmount)) {
invokeVNodeHook(vnodeHook, parentComponent, vnode)
}
if (shapeFlag & ShapeFlags.COMPONENT) {
- if (shouldKeepAlive) {
- ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
- } else {
- unmountComponent(vnode.component!, parentSuspense, doRemove)
- }
+ unmountComponent(vnode.component!, parentSuspense, doRemove)
} else {
if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
vnode.suspense!.unmount(parentSuspense, doRemove)
}
}
- if (
- ((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) &&
- !shouldKeepAlive
- ) {
+ if ((vnodeHook = props && props.onVnodeUnmounted) || shouldInvokeDirs) {
queuePostRenderEffect(() => {
vnodeHook && invokeVNodeHook(vnodeHook, parentComponent, vnode)
shouldInvokeDirs &&