]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: handle mode
authordaiwei <daiwei521@126.com>
Thu, 27 Feb 2025 14:31:45 +0000 (22:31 +0800)
committerdaiwei <daiwei521@126.com>
Thu, 27 Feb 2025 14:31:45 +0000 (22:31 +0800)
packages/runtime-core/src/components/BaseTransition.ts
packages/runtime-vapor/src/block.ts
packages/runtime-vapor/src/components/Transition.ts

index ae89f36356bf6a19c5d6fe74b2207072a4f48a9c..673d30a777aea3bd88d210c1d4f8fbd36af2a31d 100644 (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])
     },
index a4cfcea1f9c2e3c082cc8d2b260837f035657a76..383c4e8e9fdd89274eef96d0c7ae2fbab78e8c99 100644 (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()
   }
 }
index 2eb87ebffe0727738a67994960532a526644a15a..00cf52414e3f7372ceee795fbb01ee6b7a0f590d 100644 (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
   },