]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: vdom interop
authordaiwei <daiwei521@126.com>
Mon, 14 Apr 2025 02:15:25 +0000 (10:15 +0800)
committerdaiwei <daiwei521@126.com>
Mon, 14 Apr 2025 02:15:25 +0000 (10:15 +0800)
packages/runtime-core/src/components/KeepAlive.ts
packages/runtime-core/src/index.ts
packages/runtime-vapor/src/components/KeepAlive.ts
packages/runtime-vapor/src/vdomInterop.ts

index eaa10e359df0d16ddf54df80e3e26713a1752b53..0a88a3303e668fd7b596a0a36e4956a3ece39a3c 100644 (file)
@@ -1,4 +1,5 @@
 import {
+  type ComponentInternalInstance,
   type ComponentOptions,
   type ConcreteComponent,
   type GenericComponentInstance,
@@ -46,7 +47,7 @@ import { setTransitionHooks } from './BaseTransition'
 import type { ComponentRenderContext } from '../componentPublicInstance'
 import { devtoolsComponentAdded } from '../devtools'
 import { isAsyncWrapper } from '../apiAsyncComponent'
-import { isSuspense } from './Suspense'
+import { type SuspenseBoundary, isSuspense } from './Suspense'
 import { LifecycleHooks } from '../enums'
 
 type MatchPattern = string | RegExp | (string | RegExp)[]
@@ -118,14 +119,11 @@ const KeepAliveImpl: ComponentOptions = {
 
     const parentSuspense = keepAliveInstance.suspense
 
+    const { renderer } = sharedContext
     const {
-      renderer: {
-        p: patch,
-        m: move,
-        um: _unmount,
-        o: { createElement },
-      },
-    } = sharedContext
+      um: _unmount,
+      o: { createElement },
+    } = renderer
     const storageContainer = createElement('div')
 
     sharedContext.activate = (
@@ -135,72 +133,26 @@ const KeepAliveImpl: ComponentOptions = {
       namespace,
       optimized,
     ) => {
-      const instance = vnode.component!
-      move(
+      activate(
         vnode,
         container,
         anchor,
-        MoveType.ENTER,
+        renderer,
         keepAliveInstance,
         parentSuspense,
-      )
-      // in case props have changed
-      patch(
-        instance.vnode,
-        vnode,
-        container,
-        anchor,
-        instance,
-        parentSuspense,
         namespace,
-        vnode.slotScopeIds,
         optimized,
       )
-      queuePostRenderEffect(() => {
-        instance.isDeactivated = false
-        if (instance.a) {
-          invokeArrayFns(instance.a)
-        }
-        const vnodeHook = vnode.props && vnode.props.onVnodeMounted
-        if (vnodeHook) {
-          invokeVNodeHook(vnodeHook, instance.parent, vnode)
-        }
-      }, parentSuspense)
-
-      if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
-        // Update components tree
-        devtoolsComponentAdded(instance)
-      }
     }
 
     sharedContext.deactivate = (vnode: VNode) => {
-      const instance = vnode.component!
-      invalidateMount(instance.m)
-      invalidateMount(instance.a)
-
-      move(
+      deactivate(
         vnode,
         storageContainer,
-        null,
-        MoveType.LEAVE,
+        renderer,
         keepAliveInstance,
         parentSuspense,
       )
-      queuePostRenderEffect(() => {
-        if (instance.da) {
-          invokeArrayFns(instance.da)
-        }
-        const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted
-        if (vnodeHook) {
-          invokeVNodeHook(vnodeHook, instance.parent, vnode)
-        }
-        instance.isDeactivated = true
-      }, parentSuspense)
-
-      if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
-        // Update components tree
-        devtoolsComponentAdded(instance)
-      }
     }
 
     function unmount(vnode: VNode) {
@@ -487,3 +439,86 @@ export function resetShapeFlag(vnode: any): void {
 function getInnerChild(vnode: VNode) {
   return vnode.shapeFlag & ShapeFlags.SUSPENSE ? vnode.ssContent! : vnode
 }
+
+/**
+ * shared between runtime-core and runtime-vapor
+ */
+export function activate(
+  vnode: VNode,
+  container: RendererElement,
+  anchor: RendererNode | null,
+  { p: patch, m: move }: RendererInternals,
+  parentComponent: ComponentInternalInstance | null,
+  parentSuspense: SuspenseBoundary | null,
+  namespace?: ElementNamespace,
+  optimized?: boolean,
+): void {
+  const instance = vnode.component!
+  move(
+    vnode,
+    container,
+    anchor,
+    MoveType.ENTER,
+    parentComponent,
+    parentSuspense,
+  )
+  // in case props have changed
+  patch(
+    instance.vnode,
+    vnode,
+    container,
+    anchor,
+    instance,
+    parentSuspense,
+    namespace,
+    vnode.slotScopeIds,
+    optimized,
+  )
+  queuePostRenderEffect(() => {
+    instance.isDeactivated = false
+    if (instance.a) {
+      invokeArrayFns(instance.a)
+    }
+    const vnodeHook = vnode.props && vnode.props.onVnodeMounted
+    if (vnodeHook) {
+      invokeVNodeHook(vnodeHook, instance.parent, vnode)
+    }
+  }, parentSuspense)
+
+  if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
+    // Update components tree
+    devtoolsComponentAdded(instance)
+  }
+}
+
+/**
+ * shared between runtime-core and runtime-vapor
+ */
+export function deactivate(
+  vnode: VNode,
+  container: RendererElement,
+  { m: move }: RendererInternals,
+  parentComponent: ComponentInternalInstance | null,
+  parentSuspense: SuspenseBoundary | null,
+): void {
+  const instance = vnode.component!
+  invalidateMount(instance.m)
+  invalidateMount(instance.a)
+
+  move(vnode, container, null, MoveType.LEAVE, parentComponent, parentSuspense)
+  queuePostRenderEffect(() => {
+    if (instance.da) {
+      invokeArrayFns(instance.da)
+    }
+    const vnodeHook = vnode.props && vnode.props.onVnodeUnmounted
+    if (vnodeHook) {
+      invokeVNodeHook(vnodeHook, instance.parent, vnode)
+    }
+    instance.isDeactivated = true
+  }, parentSuspense)
+
+  if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
+    // Update components tree
+    devtoolsComponentAdded(instance)
+  }
+}
index 8d87d4812590a3702aeb00268d2589aa13dc7d3e..057d1158ebf60d3c1aca51159fbe1a6d088a3c96 100644 (file)
@@ -564,7 +564,13 @@ export { getComponentName } from './component'
 /**
  * @internal
  */
-export { matches, isKeepAlive, resetShapeFlag } from './components/KeepAlive'
+export {
+  matches,
+  isKeepAlive,
+  resetShapeFlag,
+  activate,
+  deactivate,
+} from './components/KeepAlive'
 /**
  * @internal
  */
index 439f0f3ff8968f08db94de0bb4df2e7b1e9d4ad5..cafefb1f1bfe574c59c2fbf5e9b6afa1aabc7fc0 100644 (file)
@@ -31,15 +31,16 @@ import { createElement } from '../dom/node'
 
 export interface KeepAliveInstance extends VaporComponentInstance {
   activate: (
-    block: VaporComponentInstance | VaporFragment,
+    instance: VaporComponentInstance,
     parentNode: ParentNode,
     anchor?: Node | null | 0,
   ) => void
-  deactivate: (block: VaporComponentInstance | VaporFragment) => void
+  deactivate: (instance: VaporComponentInstance) => void
   process: (block: Block) => void
   getCachedComponent: (
     comp: VaporComponent,
   ) => VaporComponentInstance | VaporFragment | undefined
+  getStorageContainer: () => ParentNode
 }
 
 type CacheKey = VaporComponent
@@ -128,6 +129,7 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
       })
     })
 
+    keepAliveInstance.getStorageContainer = () => storageContainer
     keepAliveInstance.getCachedComponent = comp => cache.get(comp)
 
     const process = (keepAliveInstance.process = block => {
@@ -143,18 +145,9 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
       }
     })
 
-    keepAliveInstance.activate = (block, parentNode, anchor) => {
-      current = block
-      let instance
-      if (isVaporComponent(block)) {
-        instance = block
-        insert(block.block, parentNode, anchor)
-      } else {
-        // vdom interop
-        const comp = block.nodes as any
-        insert(comp.el, parentNode, anchor)
-        instance = comp.component
-      }
+    keepAliveInstance.activate = (instance, parentNode, anchor) => {
+      current = instance
+      insert(instance.block, parentNode, anchor)
 
       queuePostFlushCb(() => {
         instance.isDeactivated = false
@@ -166,17 +159,8 @@ export const VaporKeepAliveImpl: ObjectVaporComponent = defineVaporComponent({
       }
     }
 
-    keepAliveInstance.deactivate = block => {
-      let instance
-      if (isVaporComponent(block)) {
-        instance = block
-        insert(block.block, storageContainer)
-      } else {
-        // vdom interop
-        const comp = block.nodes as any
-        insert(comp.el, storageContainer)
-        instance = comp.component
-      }
+    keepAliveInstance.deactivate = instance => {
+      insert(instance.block, storageContainer)
 
       queuePostFlushCb(() => {
         if (instance.da) invokeArrayFns(instance.da)
index 145c81e123e228c22ba81e8f519387e86a1c9b75..753cc50dc115c5769c49d4865723291b3b13a0de 100644 (file)
@@ -9,8 +9,10 @@ import {
   type Slots,
   type VNode,
   type VaporInteropInterface,
+  activate,
   createVNode,
   currentInstance,
+  deactivate,
   ensureRenderer,
   onScopeDispose,
   renderSlot,
@@ -174,7 +176,13 @@ function createVDOMComponent(
   const parentInstance = currentInstance as VaporComponentInstance
   const unmount = (parentNode?: ParentNode) => {
     if (vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
-      ;(parentInstance as KeepAliveInstance).deactivate(frag)
+      deactivate(
+        vnode,
+        (parentInstance as KeepAliveInstance).getStorageContainer(),
+        internals,
+        parentInstance as any,
+        null,
+      )
       return
     }
     internals.umt(vnode.component!, null, !!parentNode)
@@ -182,7 +190,16 @@ function createVDOMComponent(
 
   frag.insert = (parentNode, anchor) => {
     if (vnode.shapeFlag & ShapeFlags.COMPONENT_KEPT_ALIVE) {
-      ;(parentInstance as KeepAliveInstance).activate(frag, parentNode, anchor)
+      activate(
+        vnode,
+        parentNode,
+        anchor,
+        internals,
+        parentInstance as any,
+        null,
+        undefined,
+        false,
+      )
       return
     }
     if (!isMounted) {