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[]
|
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')
|
const enterCbKey: unique symbol = Symbol('_enterCb')
|
||||||
|
|
||||||
export interface BaseTransitionProps<HostElement = RendererElement> {
|
export interface BaseTransitionProps<HostElement = RendererElement> {
|
||||||
|
|
@ -88,7 +88,7 @@ export interface TransitionState {
|
||||||
isUnmounting: boolean
|
isUnmounting: boolean
|
||||||
// Track pending leave callbacks for children of the same key.
|
// 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.
|
// 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 {
|
export interface TransitionElement {
|
||||||
|
|
@ -319,6 +319,13 @@ function getLeavingNodesForType(
|
||||||
return leavingVNodesCache
|
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
|
// The transition hooks are attached to the vnode as vnode.transition
|
||||||
// and will be called at appropriate timing in the renderer.
|
// and will be called at appropriate timing in the renderer.
|
||||||
export function resolveTransitionHooks(
|
export function resolveTransitionHooks(
|
||||||
|
|
@ -328,6 +335,57 @@ export function resolveTransitionHooks(
|
||||||
instance: GenericComponentInstance,
|
instance: GenericComponentInstance,
|
||||||
postClone?: (hooks: TransitionHooks) => void,
|
postClone?: (hooks: TransitionHooks) => void,
|
||||||
): TransitionHooks {
|
): 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 {
|
const {
|
||||||
appear,
|
appear,
|
||||||
mode,
|
mode,
|
||||||
|
|
@ -345,8 +403,6 @@ export function resolveTransitionHooks(
|
||||||
onAfterAppear,
|
onAfterAppear,
|
||||||
onAppearCancelled,
|
onAppearCancelled,
|
||||||
} = props
|
} = props
|
||||||
const key = String(vnode.key)
|
|
||||||
const leavingVNodesCache = getLeavingNodesForType(state, vnode)
|
|
||||||
|
|
||||||
const callHook: TransitionHookCaller = (hook, args) => {
|
const callHook: TransitionHookCaller = (hook, args) => {
|
||||||
hook &&
|
hook &&
|
||||||
|
|
@ -388,16 +444,7 @@ export function resolveTransitionHooks(
|
||||||
el[leaveCbKey](true /* cancelled */)
|
el[leaveCbKey](true /* cancelled */)
|
||||||
}
|
}
|
||||||
// for toggled element with same key (v-if)
|
// for toggled element with same key (v-if)
|
||||||
const leavingVNode = leavingVNodesCache[key]
|
earlyRemove()
|
||||||
if (
|
|
||||||
leavingVNode &&
|
|
||||||
isSameVNodeType(vnode, leavingVNode) &&
|
|
||||||
// TODO refactor
|
|
||||||
((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]
|
|
||||||
) {
|
|
||||||
// force early removal (not cancelled)
|
|
||||||
;((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]!()
|
|
||||||
}
|
|
||||||
callHook(hook, [el])
|
callHook(hook, [el])
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -436,7 +483,7 @@ export function resolveTransitionHooks(
|
||||||
},
|
},
|
||||||
|
|
||||||
leave(el, remove) {
|
leave(el, remove) {
|
||||||
const key = String(vnode.key)
|
// const key = String(vnode.key)
|
||||||
if (el[enterCbKey]) {
|
if (el[enterCbKey]) {
|
||||||
el[enterCbKey](true /* cancelled */)
|
el[enterCbKey](true /* cancelled */)
|
||||||
}
|
}
|
||||||
|
|
@ -455,11 +502,9 @@ export function resolveTransitionHooks(
|
||||||
callHook(onAfterLeave, [el])
|
callHook(onAfterLeave, [el])
|
||||||
}
|
}
|
||||||
el[leaveCbKey] = undefined
|
el[leaveCbKey] = undefined
|
||||||
if (leavingVNodesCache[key] === vnode) {
|
unsetLeavingNodeCache()
|
||||||
delete leavingVNodesCache[key]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
leavingVNodesCache[key] = vnode
|
setLeavingNodeCache()
|
||||||
if (onLeave) {
|
if (onLeave) {
|
||||||
callAsyncHook(onLeave, [el, done])
|
callAsyncHook(onLeave, [el, done])
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -467,16 +512,8 @@ export function resolveTransitionHooks(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
clone(vnode) {
|
clone(node) {
|
||||||
const hooks = resolveTransitionHooks(
|
return cloneHooks(node)
|
||||||
vnode,
|
|
||||||
props,
|
|
||||||
state,
|
|
||||||
instance,
|
|
||||||
postClone,
|
|
||||||
)
|
|
||||||
if (postClone) postClone(hooks)
|
|
||||||
return hooks
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,8 +150,10 @@ export { registerRuntimeCompiler, isRuntimeOnly } from './component'
|
||||||
export {
|
export {
|
||||||
useTransitionState,
|
useTransitionState,
|
||||||
resolveTransitionHooks,
|
resolveTransitionHooks,
|
||||||
|
baseResolveTransitionHooks,
|
||||||
setTransitionHooks,
|
setTransitionHooks,
|
||||||
getTransitionRawChildren,
|
getTransitionRawChildren,
|
||||||
|
leaveCbKey,
|
||||||
} from './components/BaseTransition'
|
} from './components/BaseTransition'
|
||||||
export { initCustomFormatter } from './customFormatter'
|
export { initCustomFormatter } from './customFormatter'
|
||||||
|
|
||||||
|
|
@ -335,6 +337,8 @@ export type { SuspenseBoundary } from './components/Suspense'
|
||||||
export type {
|
export type {
|
||||||
TransitionState,
|
TransitionState,
|
||||||
TransitionHooks,
|
TransitionHooks,
|
||||||
|
TransitionHooksContext,
|
||||||
|
TransitionElement,
|
||||||
} from './components/BaseTransition'
|
} from './components/BaseTransition'
|
||||||
export type {
|
export type {
|
||||||
AsyncComponentOptions,
|
AsyncComponentOptions,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
import {
|
import {
|
||||||
|
type GenericComponentInstance,
|
||||||
|
type TransitionElement,
|
||||||
type TransitionHooks,
|
type TransitionHooks,
|
||||||
|
type TransitionHooksContext,
|
||||||
type TransitionProps,
|
type TransitionProps,
|
||||||
|
type TransitionState,
|
||||||
type VaporTransitionInterface,
|
type VaporTransitionInterface,
|
||||||
|
baseResolveTransitionHooks,
|
||||||
currentInstance,
|
currentInstance,
|
||||||
|
leaveCbKey,
|
||||||
registerVaporTransition,
|
registerVaporTransition,
|
||||||
resolveTransitionHooks,
|
|
||||||
useTransitionState,
|
useTransitionState,
|
||||||
} from '@vue/runtime-dom'
|
} from '@vue/runtime-dom'
|
||||||
import type { Block } from '../block'
|
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) {
|
function setTransitionHooks(block: Block, hooks: TransitionHooks) {
|
||||||
if (isVaporComponent(block)) {
|
if (isVaporComponent(block)) {
|
||||||
setTransitionHooks(block.block, hooks)
|
setTransitionHooks(block.block, hooks)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue