wip: handle mode

This commit is contained in:
daiwei 2025-02-27 22:31:45 +08:00
parent 41822e3743
commit 7cee02438f
3 changed files with 75 additions and 23 deletions

View File

@ -392,10 +392,11 @@ export function resolveTransitionHooks(
if (
leavingVNode &&
isSameVNodeType(vnode, leavingVNode) &&
(leavingVNode.el as TransitionElement)[leaveCbKey]
// TODO refactor
((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]
) {
// force early removal (not cancelled)
;(leavingVNode.el as TransitionElement)[leaveCbKey]!()
;((leavingVNode.el || leavingVNode) as TransitionElement)[leaveCbKey]!()
}
callHook(hook, [el])
},

View File

@ -19,7 +19,16 @@ export type Block = (
| DynamicFragment
| VaporComponentInstance
| Block[]
) & { transition?: TransitionHooks }
) &
TransitionBlock
export type TransitionBlock = {
transition?: TransitionHooks
applyLeavingHooks?: (
block: Block,
afterLeaveCb: () => void,
) => TransitionHooks
}
export type BlockFn = (...args: any[]) => Block
@ -29,6 +38,10 @@ export class VaporFragment {
insert?: (parent: ParentNode, anchor: Node | null) => void
remove?: (parent?: ParentNode) => void
transition?: TransitionHooks
applyLeavingHooks?: (
block: Block,
afterLeaveCb: () => void,
) => TransitionHooks
constructor(nodes: Block) {
this.nodes = nodes
@ -56,29 +69,39 @@ export class DynamicFragment extends VaporFragment {
pauseTracking()
const parent = this.anchor.parentNode
const renderNewBranch = () => {
if (render) {
this.scope = new EffectScope()
this.nodes = this.scope.run(render) || []
if (parent) insert(this.nodes, parent, this.anchor, this.transition)
} else {
this.scope = undefined
this.nodes = []
}
if (this.fallback && !isValidBlock(this.nodes)) {
parent && remove(this.nodes, parent, this.transition)
this.nodes =
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
[]
parent && insert(this.nodes, parent, this.anchor, this.transition)
}
}
// teardown previous branch
if (this.scope) {
this.scope.stop()
parent && remove(this.nodes, parent, this.transition)
}
if (render) {
this.scope = new EffectScope()
this.nodes = this.scope.run(render) || []
if (parent) insert(this.nodes, parent, this.anchor, this.transition)
} else {
this.scope = undefined
this.nodes = []
}
if (this.fallback && !isValidBlock(this.nodes)) {
parent && remove(this.nodes, parent)
this.nodes =
(this.scope || (this.scope = new EffectScope())).run(this.fallback) ||
[]
parent && insert(this.nodes, parent, this.anchor, this.transition)
if (this.transition && this.transition.mode) {
const transition = this.applyLeavingHooks!(this.nodes, renderNewBranch)
parent && remove(this.nodes, parent, transition)
resetTracking()
return
} else {
parent && remove(this.nodes, parent, this.transition)
}
}
renderNewBranch()
resetTracking()
}
}

View File

@ -11,7 +11,10 @@ import type { Block } from '../block'
import { isVaporComponent } from '../component'
export const vaporTransitionImpl: VaporTransitionInterface = {
applyTransition: (props: TransitionProps, slots: { default: () => any }) => {
applyTransition: (
props: TransitionProps,
slots: { default: () => Block },
) => {
const children = slots.default && slots.default()
if (!children) {
return
@ -30,7 +33,32 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
)
setTransitionHooks(child, enterHooks)
// TODO handle mode
const { mode } = props
// TODO check mode
child.applyLeavingHooks = (block: Block, afterLeaveCb: () => void) => {
let leavingHooks = resolveTransitionHooks(
block as any,
props,
state,
currentInstance!,
)
setTransitionHooks(block, leavingHooks)
if (mode === 'out-in') {
state.isLeaving = true
leavingHooks.afterLeave = () => {
state.isLeaving = false
afterLeaveCb()
delete leavingHooks.afterLeave
}
} else if (mode === 'in-out') {
leavingHooks.delayLeave = (block: Block, earlyRemove, delayedLeave) => {
// TODO delay leave
}
}
return leavingHooks
}
return children
},