Skip to content

Commit a8140ac

Browse files
committed
refactor: reuse code from BaseTransition
1 parent 7cee024 commit a8140ac

File tree

3 files changed

+129
-30
lines changed

3 files changed

+129
-30
lines changed

packages/runtime-core/src/components/BaseTransition.ts

Lines changed: 66 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { SchedulerJobFlags } from '../scheduler'
2525

2626
type Hook<T = () => void> = T | T[]
2727

28-
const leaveCbKey: unique symbol = Symbol('_leaveCb')
28+
export const leaveCbKey: unique symbol = Symbol('_leaveCb')
2929
const enterCbKey: unique symbol = Symbol('_enterCb')
3030

3131
export interface BaseTransitionProps<HostElement = RendererElement> {
@@ -88,7 +88,7 @@ export interface TransitionState {
8888
isUnmounting: boolean
8989
// Track pending leave callbacks for children of the same key.
9090
// This is used to force remove leaving a child when a new copy is entering.
91-
leavingVNodes: Map<any, Record<string, VNode>>
91+
leavingVNodes: Map<any, Record<string, any>>
9292
}
9393

9494
export interface TransitionElement {
@@ -319,6 +319,13 @@ function getLeavingNodesForType(
319319
return leavingVNodesCache
320320
}
321321

322+
export interface TransitionHooksContext {
323+
setLeavingNodeCache: () => void
324+
unsetLeavingNodeCache: () => void
325+
earlyRemove: () => void
326+
cloneHooks: (node: any) => TransitionHooks
327+
}
328+
322329
// The transition hooks are attached to the vnode as vnode.transition
323330
// and will be called at appropriate timing in the renderer.
324331
export function resolveTransitionHooks(
@@ -328,6 +335,57 @@ export function resolveTransitionHooks(
328335
instance: GenericComponentInstance,
329336
postClone?: (hooks: TransitionHooks) => void,
330337
): TransitionHooks {
338+
const key = String(vnode.key)
339+
const leavingVNodesCache = getLeavingNodesForType(state, vnode)
340+
const context: TransitionHooksContext = {
341+
setLeavingNodeCache: () => {
342+
leavingVNodesCache[key] = vnode
343+
},
344+
unsetLeavingNodeCache: () => {
345+
if (leavingVNodesCache[key] === vnode) {
346+
delete leavingVNodesCache[key]
347+
}
348+
},
349+
earlyRemove: () => {
350+
const leavingVNode = leavingVNodesCache[key]
351+
if (
352+
leavingVNode &&
353+
isSameVNodeType(vnode, leavingVNode) &&
354+
(leavingVNode.el as TransitionElement)[leaveCbKey]
355+
) {
356+
// force early removal (not cancelled)
357+
;(leavingVNode.el as TransitionElement)[leaveCbKey]!()
358+
}
359+
},
360+
cloneHooks: vnode => {
361+
const hooks = resolveTransitionHooks(
362+
vnode,
363+
props,
364+
state,
365+
instance,
366+
postClone,
367+
)
368+
if (postClone) postClone(hooks)
369+
return hooks
370+
},
371+
}
372+
373+
return baseResolveTransitionHooks(context, props, state, instance)
374+
}
375+
376+
export function baseResolveTransitionHooks(
377+
context: TransitionHooksContext,
378+
props: BaseTransitionProps<any>,
379+
state: TransitionState,
380+
instance: GenericComponentInstance,
381+
): TransitionHooks {
382+
const {
383+
setLeavingNodeCache,
384+
unsetLeavingNodeCache,
385+
earlyRemove,
386+
cloneHooks,
387+
} = context
388+
331389
const {
332390
appear,
333391
mode,
@@ -345,8 +403,6 @@ export function resolveTransitionHooks(
345403
onAfterAppear,
346404
onAppearCancelled,
347405
} = props
348-
const key = String(vnode.key)
349-
const leavingVNodesCache = getLeavingNodesForType(state, vnode)
350406

351407
const callHook: TransitionHookCaller = (hook, args) => {
352408
hook &&
@@ -388,16 +444,7 @@ export function resolveTransitionHooks(
388444
el[leaveCbKey](true /* cancelled */)
389445
}
390446
// for toggled element with same key (v-if)
391-
const leavingVNode = leavingVNodesCache[key]
392-
if (
393-
leavingVNode &&
394-
isSameVNodeType(vnode, leavingVNode) &&
395-
// TODO refactor
396-
((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]
397-
) {
398-
// force early removal (not cancelled)
399-
;((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]!()
400-
}
447+
earlyRemove()
401448
callHook(hook, [el])
402449
},
403450

@@ -436,7 +483,7 @@ export function resolveTransitionHooks(
436483
},
437484

438485
leave(el, remove) {
439-
const key = String(vnode.key)
486+
// const key = String(vnode.key)
440487
if (el[enterCbKey]) {
441488
el[enterCbKey](true /* cancelled */)
442489
}
@@ -455,28 +502,18 @@ export function resolveTransitionHooks(
455502
callHook(onAfterLeave, [el])
456503
}
457504
el[leaveCbKey] = undefined
458-
if (leavingVNodesCache[key] === vnode) {
459-
delete leavingVNodesCache[key]
460-
}
505+
unsetLeavingNodeCache()
461506
})
462-
leavingVNodesCache[key] = vnode
507+
setLeavingNodeCache()
463508
if (onLeave) {
464509
callAsyncHook(onLeave, [el, done])
465510
} else {
466511
done()
467512
}
468513
},
469514

470-
clone(vnode) {
471-
const hooks = resolveTransitionHooks(
472-
vnode,
473-
props,
474-
state,
475-
instance,
476-
postClone,
477-
)
478-
if (postClone) postClone(hooks)
479-
return hooks
515+
clone(node) {
516+
return cloneHooks(node)
480517
},
481518
}
482519

packages/runtime-core/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,10 @@ export { registerRuntimeCompiler, isRuntimeOnly } from './component'
150150
export {
151151
useTransitionState,
152152
resolveTransitionHooks,
153+
baseResolveTransitionHooks,
153154
setTransitionHooks,
154155
getTransitionRawChildren,
156+
leaveCbKey,
155157
} from './components/BaseTransition'
156158
export { initCustomFormatter } from './customFormatter'
157159

@@ -335,6 +337,8 @@ export type { SuspenseBoundary } from './components/Suspense'
335337
export type {
336338
TransitionState,
337339
TransitionHooks,
340+
TransitionHooksContext,
341+
TransitionElement,
338342
} from './components/BaseTransition'
339343
export type {
340344
AsyncComponentOptions,

packages/runtime-vapor/src/components/Transition.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
import {
2+
type GenericComponentInstance,
3+
type TransitionElement,
24
type TransitionHooks,
5+
type TransitionHooksContext,
36
type TransitionProps,
7+
type TransitionState,
48
type VaporTransitionInterface,
9+
baseResolveTransitionHooks,
510
currentInstance,
11+
leaveCbKey,
612
registerVaporTransition,
7-
resolveTransitionHooks,
813
useTransitionState,
914
} from '@vue/runtime-dom'
1015
import type { Block } from '../block'
@@ -64,6 +69,59 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
6469
},
6570
}
6671

72+
function resolveTransitionHooks(
73+
block: Block & { key: string },
74+
props: TransitionProps,
75+
state: TransitionState,
76+
instance: GenericComponentInstance,
77+
postClone?: (hooks: TransitionHooks) => void,
78+
): TransitionHooks {
79+
const key = String(block.key)
80+
const leavingNodeCache = getLeavingNodesForBlock(state, block)
81+
const context: TransitionHooksContext = {
82+
setLeavingNodeCache: () => {
83+
leavingNodeCache[key] = block
84+
},
85+
unsetLeavingNodeCache: () => {
86+
if (leavingNodeCache[key] === block) {
87+
delete leavingNodeCache[key]
88+
}
89+
},
90+
earlyRemove: () => {
91+
const leavingNode = leavingNodeCache[key]
92+
if (leavingNode && (leavingNode as TransitionElement)[leaveCbKey]) {
93+
// force early removal (not cancelled)
94+
;(leavingNode as TransitionElement)[leaveCbKey]!()
95+
}
96+
},
97+
cloneHooks: block => {
98+
const hooks = resolveTransitionHooks(
99+
block,
100+
props,
101+
state,
102+
instance,
103+
postClone,
104+
)
105+
if (postClone) postClone(hooks)
106+
return hooks
107+
},
108+
}
109+
return baseResolveTransitionHooks(context, props, state, instance)
110+
}
111+
112+
function getLeavingNodesForBlock(
113+
state: TransitionState,
114+
block: Block,
115+
): Record<string, Block> {
116+
const { leavingVNodes } = state
117+
let leavingNodesCache = leavingVNodes.get(block)!
118+
if (!leavingNodesCache) {
119+
leavingNodesCache = Object.create(null)
120+
leavingVNodes.set(block, leavingNodesCache)
121+
}
122+
return leavingNodesCache
123+
}
124+
67125
function setTransitionHooks(block: Block, hooks: TransitionHooks) {
68126
if (isVaporComponent(block)) {
69127
setTransitionHooks(block.block, hooks)

0 commit comments

Comments
 (0)