mirror of https://github.com/vuejs/core.git
refactor: reuse code from BaseTransition
This commit is contained in:
parent
7cee02438f
commit
a8140ac826
|
|
@ -25,7 +25,7 @@ import { SchedulerJobFlags } from '../scheduler'
|
|||
|
||||
type Hook<T = () => void> = T | T[]
|
||||
|
||||
const leaveCbKey: unique symbol = Symbol('_leaveCb')
|
||||
export const leaveCbKey: unique symbol = Symbol('_leaveCb')
|
||||
const enterCbKey: unique symbol = Symbol('_enterCb')
|
||||
|
||||
export interface BaseTransitionProps<HostElement = RendererElement> {
|
||||
|
|
@ -88,7 +88,7 @@ export interface TransitionState {
|
|||
isUnmounting: boolean
|
||||
// Track pending leave callbacks for children of the same key.
|
||||
// This is used to force remove leaving a child when a new copy is entering.
|
||||
leavingVNodes: Map<any, Record<string, VNode>>
|
||||
leavingVNodes: Map<any, Record<string, any>>
|
||||
}
|
||||
|
||||
export interface TransitionElement {
|
||||
|
|
@ -319,6 +319,13 @@ function getLeavingNodesForType(
|
|||
return leavingVNodesCache
|
||||
}
|
||||
|
||||
export interface TransitionHooksContext {
|
||||
setLeavingNodeCache: () => void
|
||||
unsetLeavingNodeCache: () => void
|
||||
earlyRemove: () => void
|
||||
cloneHooks: (node: any) => TransitionHooks
|
||||
}
|
||||
|
||||
// The transition hooks are attached to the vnode as vnode.transition
|
||||
// and will be called at appropriate timing in the renderer.
|
||||
export function resolveTransitionHooks(
|
||||
|
|
@ -328,6 +335,57 @@ export function resolveTransitionHooks(
|
|||
instance: GenericComponentInstance,
|
||||
postClone?: (hooks: TransitionHooks) => void,
|
||||
): TransitionHooks {
|
||||
const key = String(vnode.key)
|
||||
const leavingVNodesCache = getLeavingNodesForType(state, vnode)
|
||||
const context: TransitionHooksContext = {
|
||||
setLeavingNodeCache: () => {
|
||||
leavingVNodesCache[key] = vnode
|
||||
},
|
||||
unsetLeavingNodeCache: () => {
|
||||
if (leavingVNodesCache[key] === vnode) {
|
||||
delete leavingVNodesCache[key]
|
||||
}
|
||||
},
|
||||
earlyRemove: () => {
|
||||
const leavingVNode = leavingVNodesCache[key]
|
||||
if (
|
||||
leavingVNode &&
|
||||
isSameVNodeType(vnode, leavingVNode) &&
|
||||
(leavingVNode.el as TransitionElement)[leaveCbKey]
|
||||
) {
|
||||
// force early removal (not cancelled)
|
||||
;(leavingVNode.el as TransitionElement)[leaveCbKey]!()
|
||||
}
|
||||
},
|
||||
cloneHooks: vnode => {
|
||||
const hooks = resolveTransitionHooks(
|
||||
vnode,
|
||||
props,
|
||||
state,
|
||||
instance,
|
||||
postClone,
|
||||
)
|
||||
if (postClone) postClone(hooks)
|
||||
return hooks
|
||||
},
|
||||
}
|
||||
|
||||
return baseResolveTransitionHooks(context, props, state, instance)
|
||||
}
|
||||
|
||||
export function baseResolveTransitionHooks(
|
||||
context: TransitionHooksContext,
|
||||
props: BaseTransitionProps<any>,
|
||||
state: TransitionState,
|
||||
instance: GenericComponentInstance,
|
||||
): TransitionHooks {
|
||||
const {
|
||||
setLeavingNodeCache,
|
||||
unsetLeavingNodeCache,
|
||||
earlyRemove,
|
||||
cloneHooks,
|
||||
} = context
|
||||
|
||||
const {
|
||||
appear,
|
||||
mode,
|
||||
|
|
@ -345,8 +403,6 @@ export function resolveTransitionHooks(
|
|||
onAfterAppear,
|
||||
onAppearCancelled,
|
||||
} = props
|
||||
const key = String(vnode.key)
|
||||
const leavingVNodesCache = getLeavingNodesForType(state, vnode)
|
||||
|
||||
const callHook: TransitionHookCaller = (hook, args) => {
|
||||
hook &&
|
||||
|
|
@ -388,16 +444,7 @@ export function resolveTransitionHooks(
|
|||
el[leaveCbKey](true /* cancelled */)
|
||||
}
|
||||
// for toggled element with same key (v-if)
|
||||
const leavingVNode = leavingVNodesCache[key]
|
||||
if (
|
||||
leavingVNode &&
|
||||
isSameVNodeType(vnode, leavingVNode) &&
|
||||
// TODO refactor
|
||||
((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]
|
||||
) {
|
||||
// force early removal (not cancelled)
|
||||
;((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]!()
|
||||
}
|
||||
earlyRemove()
|
||||
callHook(hook, [el])
|
||||
},
|
||||
|
||||
|
|
@ -436,7 +483,7 @@ export function resolveTransitionHooks(
|
|||
},
|
||||
|
||||
leave(el, remove) {
|
||||
const key = String(vnode.key)
|
||||
// const key = String(vnode.key)
|
||||
if (el[enterCbKey]) {
|
||||
el[enterCbKey](true /* cancelled */)
|
||||
}
|
||||
|
|
@ -455,11 +502,9 @@ export function resolveTransitionHooks(
|
|||
callHook(onAfterLeave, [el])
|
||||
}
|
||||
el[leaveCbKey] = undefined
|
||||
if (leavingVNodesCache[key] === vnode) {
|
||||
delete leavingVNodesCache[key]
|
||||
}
|
||||
unsetLeavingNodeCache()
|
||||
})
|
||||
leavingVNodesCache[key] = vnode
|
||||
setLeavingNodeCache()
|
||||
if (onLeave) {
|
||||
callAsyncHook(onLeave, [el, done])
|
||||
} else {
|
||||
|
|
@ -467,16 +512,8 @@ export function resolveTransitionHooks(
|
|||
}
|
||||
},
|
||||
|
||||
clone(vnode) {
|
||||
const hooks = resolveTransitionHooks(
|
||||
vnode,
|
||||
props,
|
||||
state,
|
||||
instance,
|
||||
postClone,
|
||||
)
|
||||
if (postClone) postClone(hooks)
|
||||
return hooks
|
||||
clone(node) {
|
||||
return cloneHooks(node)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,8 +150,10 @@ export { registerRuntimeCompiler, isRuntimeOnly } from './component'
|
|||
export {
|
||||
useTransitionState,
|
||||
resolveTransitionHooks,
|
||||
baseResolveTransitionHooks,
|
||||
setTransitionHooks,
|
||||
getTransitionRawChildren,
|
||||
leaveCbKey,
|
||||
} from './components/BaseTransition'
|
||||
export { initCustomFormatter } from './customFormatter'
|
||||
|
||||
|
|
@ -335,6 +337,8 @@ export type { SuspenseBoundary } from './components/Suspense'
|
|||
export type {
|
||||
TransitionState,
|
||||
TransitionHooks,
|
||||
TransitionHooksContext,
|
||||
TransitionElement,
|
||||
} from './components/BaseTransition'
|
||||
export type {
|
||||
AsyncComponentOptions,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import {
|
||||
type GenericComponentInstance,
|
||||
type TransitionElement,
|
||||
type TransitionHooks,
|
||||
type TransitionHooksContext,
|
||||
type TransitionProps,
|
||||
type TransitionState,
|
||||
type VaporTransitionInterface,
|
||||
baseResolveTransitionHooks,
|
||||
currentInstance,
|
||||
leaveCbKey,
|
||||
registerVaporTransition,
|
||||
resolveTransitionHooks,
|
||||
useTransitionState,
|
||||
} from '@vue/runtime-dom'
|
||||
import type { Block } from '../block'
|
||||
|
|
@ -64,6 +69,59 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
|
|||
},
|
||||
}
|
||||
|
||||
function resolveTransitionHooks(
|
||||
block: Block & { key: string },
|
||||
props: TransitionProps,
|
||||
state: TransitionState,
|
||||
instance: GenericComponentInstance,
|
||||
postClone?: (hooks: TransitionHooks) => void,
|
||||
): TransitionHooks {
|
||||
const key = String(block.key)
|
||||
const leavingNodeCache = getLeavingNodesForBlock(state, block)
|
||||
const context: TransitionHooksContext = {
|
||||
setLeavingNodeCache: () => {
|
||||
leavingNodeCache[key] = block
|
||||
},
|
||||
unsetLeavingNodeCache: () => {
|
||||
if (leavingNodeCache[key] === block) {
|
||||
delete leavingNodeCache[key]
|
||||
}
|
||||
},
|
||||
earlyRemove: () => {
|
||||
const leavingNode = leavingNodeCache[key]
|
||||
if (leavingNode && (leavingNode as TransitionElement)[leaveCbKey]) {
|
||||
// force early removal (not cancelled)
|
||||
;(leavingNode as TransitionElement)[leaveCbKey]!()
|
||||
}
|
||||
},
|
||||
cloneHooks: block => {
|
||||
const hooks = resolveTransitionHooks(
|
||||
block,
|
||||
props,
|
||||
state,
|
||||
instance,
|
||||
postClone,
|
||||
)
|
||||
if (postClone) postClone(hooks)
|
||||
return hooks
|
||||
},
|
||||
}
|
||||
return baseResolveTransitionHooks(context, props, state, instance)
|
||||
}
|
||||
|
||||
function getLeavingNodesForBlock(
|
||||
state: TransitionState,
|
||||
block: Block,
|
||||
): Record<string, Block> {
|
||||
const { leavingVNodes } = state
|
||||
let leavingNodesCache = leavingVNodes.get(block)!
|
||||
if (!leavingNodesCache) {
|
||||
leavingNodesCache = Object.create(null)
|
||||
leavingVNodes.set(block, leavingNodesCache)
|
||||
}
|
||||
return leavingNodesCache
|
||||
}
|
||||
|
||||
function setTransitionHooks(block: Block, hooks: TransitionHooks) {
|
||||
if (isVaporComponent(block)) {
|
||||
setTransitionHooks(block.block, hooks)
|
||||
|
|
|
|||
Loading…
Reference in New Issue