wip: save

This commit is contained in:
daiwei 2025-03-04 10:34:28 +08:00
parent 1e7905408a
commit 75de3bb9ff
3 changed files with 36 additions and 74 deletions

View File

@ -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, any>>
leavingNodes: Map<any, Record<string, any>>
}
export interface TransitionElement {
@ -104,7 +104,7 @@ export function useTransitionState(): TransitionState {
isMounted: false,
isLeaving: false,
isUnmounting: false,
leavingVNodes: new Map(),
leavingNodes: new Map(),
}
onMounted(() => {
state.isMounted = true
@ -310,11 +310,11 @@ function getLeavingNodesForType(
state: TransitionState,
vnode: VNode,
): Record<string, VNode> {
const { leavingVNodes } = state
let leavingVNodesCache = leavingVNodes.get(vnode.type)!
const { leavingNodes } = state
let leavingVNodesCache = leavingNodes.get(vnode.type)!
if (!leavingVNodesCache) {
leavingVNodesCache = Object.create(null)
leavingVNodes.set(vnode.type, leavingVNodesCache)
leavingNodes.set(vnode.type, leavingVNodesCache)
}
return leavingVNodesCache
}

View File

@ -29,8 +29,8 @@ export type Block = (
TransitionBlock
export interface VaporTransitionHooks extends TransitionHooks {
state?: TransitionState
props?: TransitionProps
state: TransitionState
props: TransitionProps
}
export type TransitionBlock = {
@ -74,16 +74,14 @@ export class DynamicFragment extends VaporFragment {
pauseTracking()
const parent = this.anchor.parentNode
const transition = this.transition
const renderBranch = () => {
if (render) {
const transition = this.transition
this.scope = new EffectScope()
this.nodes = this.scope.run(render) || []
if (transition) {
this.transitionChild = applyTransitionEnterHooks(
this.nodes,
transition.state!,
transition.props!,
transition,
)
}
@ -97,15 +95,9 @@ export class DynamicFragment extends VaporFragment {
// teardown previous branch
if (this.scope) {
this.scope.stop()
const mode = this.transition && this.transition.mode
const mode = transition && transition.mode
if (mode) {
applyTransitionLeaveHooks(
this.nodes,
this.transition!.state!,
this.transition!.props!,
renderBranch,
this.transition,
)
applyTransitionLeaveHooks(this.nodes, transition, renderBranch)
parent && remove(this.nodes, parent)
if (mode === 'out-in') {
resetTracking()

View File

@ -35,40 +35,35 @@ export const vaporTransitionImpl: VaporTransitionInterface = {
warn(`invalid <transition> mode: ${mode}`)
}
applyTransitionEnterHooks(
children,
useTransitionState(),
applyTransitionEnterHooks(children, {
state: useTransitionState(),
props,
undefined,
false,
)
} as VaporTransitionHooks)
return children
},
}
const getTransitionHooksContext = (
key: string,
block: Block,
key: String,
props: TransitionProps,
state: TransitionState,
instance: GenericComponentInstance,
postClone: ((hooks: TransitionHooks) => void) | undefined,
) => {
const { leavingNodes } = state
const context: TransitionHooksContext = {
setLeavingNodeCache: el => {
const leavingNodeCache = getLeavingNodesForBlock(state, block)
leavingNodeCache[key] = el
leavingNodes.set(key, el)
},
unsetLeavingNodeCache: el => {
const leavingNodeCache = getLeavingNodesForBlock(state, block)
if (leavingNodeCache[key] === el) {
delete leavingNodeCache[key]
const leavingNode = leavingNodes.get(key)
if (leavingNode === el) {
leavingNodes.delete(key)
}
},
earlyRemove: () => {
const leavingNodeCache = getLeavingNodesForBlock(state, block)
const leavingNode = leavingNodeCache[key]
const leavingNode = leavingNodes.get(key)
if (leavingNode && (leavingNode as TransitionElement)[leaveCbKey]) {
// force early removal (not cancelled)
;(leavingNode as TransitionElement)[leaveCbKey]!()
@ -96,39 +91,24 @@ function resolveTransitionHooks(
instance: GenericComponentInstance,
postClone?: (hooks: TransitionHooks) => void,
): VaporTransitionHooks {
const key = String(block.key)
const context = getTransitionHooksContext(
key,
block,
String(block.key),
props,
state,
instance,
postClone,
)
const hooks: VaporTransitionHooks = baseResolveTransitionHooks(
const hooks = baseResolveTransitionHooks(
context,
props,
state,
instance,
)
) as VaporTransitionHooks
hooks.state = state
hooks.props = props
return hooks
}
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: VaporTransitionHooks) {
if (!isFragment(block)) {
block.transition = hooks
@ -137,28 +117,20 @@ function setTransitionHooks(block: Block, hooks: VaporTransitionHooks) {
export function applyTransitionEnterHooks(
block: Block,
state: TransitionState,
props: TransitionProps,
enterHooks?: VaporTransitionHooks,
clone: boolean = true,
hooks: VaporTransitionHooks,
): Block | undefined {
const child = findElementChild(block)
if (child) {
if (!enterHooks) {
enterHooks = resolveTransitionHooks(
child,
props,
state,
currentInstance!,
hooks => (enterHooks = hooks),
)
}
setTransitionHooks(
const { props, state, delayedLeave } = hooks
let enterHooks = resolveTransitionHooks(
child,
clone ? enterHooks.clone(child as any) : enterHooks,
props,
state,
currentInstance!,
hooks => (enterHooks = hooks as VaporTransitionHooks),
)
enterHooks.delayedLeave = delayedLeave
setTransitionHooks(child, enterHooks)
if (isFragment(block)) {
block.transitionChild = child
}
@ -168,15 +140,14 @@ export function applyTransitionEnterHooks(
export function applyTransitionLeaveHooks(
block: Block,
state: TransitionState,
props: TransitionProps,
enterHooks: VaporTransitionHooks,
afterLeaveCb: () => void,
enterHooks: TransitionHooks,
): void {
const leavingBlock = findElementChild(block)
if (!leavingBlock) return undefined
let leavingHooks = resolveTransitionHooks(
const { props, state } = enterHooks
const leavingHooks = resolveTransitionHooks(
leavingBlock,
props,
state,
@ -198,8 +169,7 @@ export function applyTransitionLeaveHooks(
earlyRemove,
delayedLeave,
) => {
const leavingNodeCache = getLeavingNodesForBlock(state, leavingBlock)
leavingNodeCache[String(leavingBlock.key)] = leavingBlock
state.leavingNodes.set(String(leavingBlock.key), leavingBlock)
// early removal callback
block[leaveCbKey] = () => {
earlyRemove()