feat(transition): handle persisted mode

This commit is contained in:
Evan You
2019-11-22 23:21:39 -05:00
parent cbc2044752
commit 1b8236615e
4 changed files with 75 additions and 26 deletions

View File

@@ -17,6 +17,12 @@ import { ShapeFlags } from '../shapeFlags'
export interface TransitionProps {
mode?: 'in-out' | 'out-in' | 'default'
appear?: boolean
// If true, indicates this is a transition that doesn't actually insert/remove
// the element, but toggles the show / hidden status instead.
// The transition hooks are injected, but will be skipped by the renderer.
// Instead, a custom directive can control the transition by calling the
// injected hooks (e.g. v-show).
persisted?: boolean
// enter
onBeforeEnter?: (el: any) => void
onEnter?: (el: any, done: () => void) => void
@@ -139,6 +145,7 @@ if (__DEV__) {
;(TransitionImpl as ComponentOptions).props = {
mode: String,
appear: Boolean,
persisted: Boolean,
// enter
onBeforeEnter: Function,
onEnter: Function,
@@ -161,6 +168,7 @@ export const Transition = (TransitionImpl as any) as {
}
export interface TransitionHooks {
persisted: boolean
beforeEnter(el: object): void
enter(el: object): void
leave(el: object, remove: () => void): void
@@ -173,6 +181,7 @@ export interface TransitionHooks {
function resolveTransitionHooks(
{
appear,
persisted = false,
onBeforeEnter,
onEnter,
onAfterEnter,
@@ -188,6 +197,7 @@ function resolveTransitionHooks(
performDelayedLeave: () => void
): TransitionHooks {
return {
persisted,
beforeEnter(el) {
if (!isMounted && !appear) {
return
@@ -202,7 +212,10 @@ function resolveTransitionHooks(
if (!isMounted && !appear) {
return
}
let called = false
const afterEnter = (pendingCallbacks.enter = (cancelled?) => {
if (called) return
called = true
if (cancelled) {
callHook(onEnterCancelled, [el])
} else {
@@ -223,7 +236,10 @@ function resolveTransitionHooks(
pendingCallbacks.enter(true /* cancelled */)
}
callHook(onBeforeLeave, [el])
let called = false
const afterLeave = (pendingCallbacks.leave = (cancelled?) => {
if (called) return
called = true
remove()
if (cancelled) {
callHook(onLeaveCancelled, [el])

View File

@@ -367,7 +367,7 @@ export function createRenderer<
invokeDirectiveHook(props.onVnodeBeforeMount, parentComponent, vnode)
}
}
if (transition != null) {
if (transition != null && !transition.persisted) {
transition.beforeEnter(el)
}
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
@@ -385,11 +385,14 @@ export function createRenderer<
}
hostInsert(el, container, anchor)
const vnodeMountedHook = props && props.onVnodeMounted
if (vnodeMountedHook != null || transition != null) {
if (
vnodeMountedHook != null ||
(transition != null && !transition.persisted)
) {
queuePostRenderEffect(() => {
vnodeMountedHook &&
invokeDirectiveHook(vnodeMountedHook, parentComponent, vnode)
transition && transition.enter(el)
transition && !transition.persisted && transition.enter(el)
}, parentSuspense)
}
}
@@ -1468,11 +1471,19 @@ export function createRenderer<
const remove = () => {
hostRemove(vnode.el!)
if (anchor != null) hostRemove(anchor)
if (transition != null && transition.afterLeave) {
if (
transition != null &&
!transition.persisted &&
transition.afterLeave
) {
transition.afterLeave()
}
}
if (vnode.shapeFlag & ShapeFlags.ELEMENT && transition != null) {
if (
vnode.shapeFlag & ShapeFlags.ELEMENT &&
transition != null &&
!transition.persisted
) {
const { leave, delayLeave } = transition
const performLeave = () => leave(el!, remove)
if (delayLeave) {