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