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

View File

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

View File

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