Просмотр исходного кода

refactor(runtime-vapor): move render context handling into VaporFragment (#14595)

edison 3 месяцев назад
Родитель
Сommit
974c204d50

+ 6 - 18
packages/runtime-vapor/src/components/Teleport.ts

@@ -33,7 +33,6 @@ import { rawPropsProxyHandlers } from '../componentProps'
 import { renderEffect } from '../renderEffect'
 import { extend, isArray } from '@vue/shared'
 import { VaporFragment, isFragment } from '../fragment'
-import { currentKeepAliveCtx, setCurrentKeepAliveCtx } from './KeepAlive'
 import {
   advanceHydrationNode,
   currentHydrationNode,
@@ -44,11 +43,7 @@ import {
   setCurrentHydrationNode,
 } from '../dom/hydration'
 import type { DefineVaporSetupFnComponent } from '../apiDefineComponent'
-import {
-  currentSlotOwner,
-  getScopeOwner,
-  setCurrentSlotOwner,
-} from '../componentSlots'
+import { getScopeOwner } from '../componentSlots'
 
 const VaporTeleportImpl = {
   name: 'VaporTeleport',
@@ -75,8 +70,6 @@ export class TeleportFragment extends VaporFragment {
   private childrenInitialized = false
   private readonly ownerInstance =
     currentInstance as VaporComponentInstance | null
-  private readonly slotOwner = currentSlotOwner
-  private readonly keepAliveCtx = currentKeepAliveCtx
 
   target?: ParentNode | null
   targetAnchor?: Node | null
@@ -127,18 +120,13 @@ export class TeleportFragment extends VaporFragment {
     const prevInstance = setCurrentInstance(this.ownerInstance)
     try {
       this.childrenInitialized = true
-      renderEffect(() => {
-        const prevOwner = setCurrentSlotOwner(this.slotOwner)
-        const prevKeepAliveCtx = setCurrentKeepAliveCtx(this.keepAliveCtx)
-        try {
+      renderEffect(() =>
+        this.runWithRenderCtx(() =>
           this.handleChildrenUpdate(
             this.rawSlots!.default && (this.rawSlots!.default as BlockFn)(),
-          )
-        } finally {
-          setCurrentKeepAliveCtx(prevKeepAliveCtx)
-          setCurrentSlotOwner(prevOwner)
-        }
-      })
+          ),
+        ),
+      )
       this.bindChildren(this.nodes)
     } finally {
       setCurrentInstance(...prevInstance)

+ 16 - 13
packages/runtime-vapor/src/fragment.ts

@@ -70,9 +70,24 @@ export class VaporFragment<
   // hooks
   onUpdated?: ((nodes?: Block) => void)[]
 
+  // render context
+  readonly slotOwner: VaporComponentInstance | null = currentSlotOwner
+  readonly keepAliveCtx: VaporKeepAliveContext | null = currentKeepAliveCtx
+
   constructor(nodes: T) {
     this.nodes = nodes
   }
+
+  protected runWithRenderCtx<R>(fn: () => R): R {
+    const prevSlotOwner = setCurrentSlotOwner(this.slotOwner)
+    const prevKeepAliveCtx = setCurrentKeepAliveCtx(this.keepAliveCtx)
+    try {
+      return fn()
+    } finally {
+      setCurrentKeepAliveCtx(prevKeepAliveCtx)
+      setCurrentSlotOwner(prevSlotOwner)
+    }
+  }
 }
 
 export class ForFragment extends VaporFragment<Block[]> {
@@ -92,11 +107,6 @@ export class DynamicFragment extends VaporFragment {
 
   // fallthrough attrs
   attrs?: Record<string, any>
-
-  keepAliveCtx: VaporKeepAliveContext | null
-
-  slotOwner: VaporComponentInstance | null
-
   constructor(
     anchorLabel?: string,
     keyed: boolean = false,
@@ -104,8 +114,6 @@ export class DynamicFragment extends VaporFragment {
   ) {
     super([])
     this.keyed = keyed
-    this.slotOwner = currentSlotOwner
-    this.keepAliveCtx = currentKeepAliveCtx
     if (isHydrating) {
       this.anchorLabel = anchorLabel
       if (locate) locateHydrationNode()
@@ -214,19 +222,14 @@ export class DynamicFragment extends VaporFragment {
         this.scope = new EffectScope()
       }
 
-      const prevSlotOwner = setCurrentSlotOwner(this.slotOwner)
-      // set currentKeepAliveCtx so nested DynamicFragments and components can capture it
-      const prevKeepAliveCtx = setCurrentKeepAliveCtx(keepAliveCtx)
       const needBranchKey = keepAliveCtx && this.keyed
       const prevBranchKey = needBranchKey
         ? keepAliveCtx.setCurrentBranchKey(this.current)
         : undefined
       try {
-        this.nodes = this.scope.run(render) || []
+        this.nodes = this.runWithRenderCtx(() => this.scope!.run(render) || [])
       } finally {
         if (needBranchKey) keepAliveCtx.setCurrentBranchKey(prevBranchKey)
-        setCurrentKeepAliveCtx(prevKeepAliveCtx)
-        setCurrentSlotOwner(prevSlotOwner)
       }
 
       // set key on blocks