fix(runtime-core): transition hooks can be arrays of functions (#5177)

This commit is contained in:
Kael 2022-05-11 11:56:57 +10:00 committed by GitHub
parent da10dd7de9
commit fec12d7dcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -16,10 +16,12 @@ import { warn } from '../warning'
import { isKeepAlive } from './KeepAlive' import { isKeepAlive } from './KeepAlive'
import { toRaw } from '@vue/reactivity' import { toRaw } from '@vue/reactivity'
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling' import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
import { ShapeFlags, PatchFlags } from '@vue/shared' import { ShapeFlags, PatchFlags, isArray } from '@vue/shared'
import { onBeforeUnmount, onMounted } from '../apiLifecycle' import { onBeforeUnmount, onMounted } from '../apiLifecycle'
import { RendererElement } from '../renderer' import { RendererElement } from '../renderer'
type Hook<T = () => void> = T | T[]
export interface BaseTransitionProps<HostElement = RendererElement> { export interface BaseTransitionProps<HostElement = RendererElement> {
mode?: 'in-out' | 'out-in' | 'default' mode?: 'in-out' | 'out-in' | 'default'
appear?: boolean appear?: boolean
@ -34,20 +36,20 @@ export interface BaseTransitionProps<HostElement = RendererElement> {
// Hooks. Using camel case for easier usage in render functions & JSX. // Hooks. Using camel case for easier usage in render functions & JSX.
// In templates these can be written as @before-enter="xxx" as prop names // In templates these can be written as @before-enter="xxx" as prop names
// are camelized. // are camelized.
onBeforeEnter?: (el: HostElement) => void onBeforeEnter?: Hook<(el: HostElement) => void>
onEnter?: (el: HostElement, done: () => void) => void onEnter?: Hook<(el: HostElement, done: () => void) => void>
onAfterEnter?: (el: HostElement) => void onAfterEnter?: Hook<(el: HostElement) => void>
onEnterCancelled?: (el: HostElement) => void onEnterCancelled?: Hook<(el: HostElement) => void>
// leave // leave
onBeforeLeave?: (el: HostElement) => void onBeforeLeave?: Hook<(el: HostElement) => void>
onLeave?: (el: HostElement, done: () => void) => void onLeave?: Hook<(el: HostElement, done: () => void) => void>
onAfterLeave?: (el: HostElement) => void onAfterLeave?: Hook<(el: HostElement) => void>
onLeaveCancelled?: (el: HostElement) => void // only fired in persisted mode onLeaveCancelled?: Hook<(el: HostElement) => void> // only fired in persisted mode
// appear // appear
onBeforeAppear?: (el: HostElement) => void onBeforeAppear?: Hook<(el: HostElement) => void>
onAppear?: (el: HostElement, done: () => void) => void onAppear?: Hook<(el: HostElement, done: () => void) => void>
onAfterAppear?: (el: HostElement) => void onAfterAppear?: Hook<(el: HostElement) => void>
onAppearCancelled?: (el: HostElement) => void onAppearCancelled?: Hook<(el: HostElement) => void>
} }
export interface TransitionHooks< export interface TransitionHooks<
@ -69,9 +71,9 @@ export interface TransitionHooks<
delayedLeave?(): void delayedLeave?(): void
} }
export type TransitionHookCaller = ( export type TransitionHookCaller = <T extends any[] = [el: any]>(
hook: ((el: any) => void) | Array<(el: any) => void> | undefined, hook: Hook<(...args: T) => void> | undefined,
args?: any[] args?: T
) => void ) => void
export type PendingCallback = (cancelled?: boolean) => void export type PendingCallback = (cancelled?: boolean) => void
@ -331,6 +333,19 @@ export function resolveTransitionHooks(
) )
} }
const callAsyncHook = (
hook: Hook<(el: any, done: () => void) => void>,
args: [TransitionElement, () => void]
) => {
const done = args[1]
callHook(hook, args)
if (isArray(hook)) {
if (hook.every(hook => hook.length <= 1)) done()
} else if (hook.length <= 1) {
done()
}
}
const hooks: TransitionHooks<TransitionElement> = { const hooks: TransitionHooks<TransitionElement> = {
mode, mode,
persisted, persisted,
@ -388,10 +403,7 @@ export function resolveTransitionHooks(
el._enterCb = undefined el._enterCb = undefined
}) })
if (hook) { if (hook) {
hook(el, done) callAsyncHook(hook, [el, done])
if (hook.length <= 1) {
done()
}
} else { } else {
done() done()
} }
@ -423,10 +435,7 @@ export function resolveTransitionHooks(
}) })
leavingVNodesCache[key] = vnode leavingVNodesCache[key] = vnode
if (onLeave) { if (onLeave) {
onLeave(el, done) callAsyncHook(onLeave, [el, done])
if (onLeave.length <= 1) {
done()
}
} else { } else {
done() done()
} }