Преглед изворни кода

fix: use currentSlotConsumer as parent until new instance is created

daiwei пре 5 месеци
родитељ
комит
48774eeed1

+ 2 - 1
packages/runtime-vapor/__tests__/apiInject.spec.ts

@@ -17,6 +17,7 @@ import {
   createVaporApp,
   defineVaporComponent,
   renderEffect,
+  withVaporCtx,
 } from '../src'
 import { makeRender } from './_utils'
 import { setElementText } from '../src/dom/prop'
@@ -388,7 +389,7 @@ describe('api: provide/inject', () => {
     const { host } = define({
       setup() {
         return createComponent(Parent, null, {
-          default: () => createComponent(Child),
+          default: withVaporCtx(() => createComponent(Child)),
         })
       },
     }).render()

+ 5 - 4
packages/runtime-vapor/src/component.ts

@@ -69,10 +69,11 @@ import {
   type RawSlots,
   type StaticSlots,
   type VaporSlot,
-  currentSlotConsumer,
   currentSlotOwner,
   dynamicSlotsProxyHandlers,
+  getParentInstance,
   getSlot,
+  setUseSlotConsumer,
 } from './componentSlots'
 import { hmrReload, hmrRerender } from './hmr'
 import {
@@ -193,9 +194,7 @@ export function createComponent(
     resetInsertionState()
   }
 
-  // when rendering components in slot, currentInstance is changed in withVaporCtx
-  // should use currentSlotConsumer as parent
-  const parentInstance = currentSlotConsumer || currentInstance
+  const parentInstance = getParentInstance()
 
   if (
     isSingleRoot &&
@@ -612,6 +611,8 @@ export class VaporComponentInstance implements GenericComponentInstance {
     if (comp.ce) {
       comp.ce(this)
     }
+
+    setUseSlotConsumer(false)
   }
 
   /**

+ 13 - 0
packages/runtime-vapor/src/componentSlots.ts

@@ -141,6 +141,17 @@ function setCurrentSlotConsumer(consumer: GenericComponentInstance | null) {
   }
 }
 
+export let useSlotConsumer = false
+export function setUseSlotConsumer(value: boolean): void {
+  useSlotConsumer = value
+}
+
+export function getParentInstance(): GenericComponentInstance | null {
+  // when rendering components in slot, currentInstance is changed in withVaporCtx
+  // should use currentSlotConsumer as parent until new instance is created
+  return useSlotConsumer ? currentSlotConsumer : currentInstance
+}
+
 /**
  * Wrap a slot function to memoize currentInstance
  * 1. ensure correct currentInstance in forwarded slots
@@ -149,6 +160,7 @@ function setCurrentSlotConsumer(consumer: GenericComponentInstance | null) {
 export function withVaporCtx(fn: Function): BlockFn {
   const owner = currentInstance
   return (...args: any[]) => {
+    useSlotConsumer = true
     const prev = setCurrentInstance(owner)
     const prevOwner = setCurrentSlotOwner(owner)
     const prevConsumer = setCurrentSlotConsumer(prev[0])
@@ -158,6 +170,7 @@ export function withVaporCtx(fn: Function): BlockFn {
       setCurrentSlotConsumer(prevConsumer)
       setCurrentSlotOwner(prevOwner)
       setCurrentInstance(...prev)
+      useSlotConsumer = false
     }
   }
 }

+ 3 - 4
packages/runtime-vapor/src/vdomInterop.ts

@@ -60,9 +60,9 @@ import {
 import { type RawProps, rawPropsProxyHandlers } from './componentProps'
 import type { RawSlots, VaporSlot } from './componentSlots'
 import {
-  currentSlotConsumer,
   currentSlotOwner,
   currentSlotScopeIds,
+  getParentInstance,
 } from './componentSlots'
 import { renderEffect } from './renderEffect'
 import { _next, createTextNode } from './dom/node'
@@ -280,8 +280,7 @@ function createVDOMComponent(
   rawProps?: LooseRawProps | null,
   rawSlots?: LooseRawSlots | null,
 ): VaporFragment {
-  const parentInstance = (currentSlotConsumer ||
-    currentInstance) as VaporComponentInstance
+  const parentInstance = getParentInstance() as VaporComponentInstance | null
   const frag = new VaporFragment([])
   const vnode = (frag.vnode = createVNode(
     component,
@@ -323,7 +322,7 @@ function createVDOMComponent(
     if (vnode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
       vdomDeactivate(
         vnode,
-        findParentKeepAlive(parentInstance)!.getStorageContainer(),
+        findParentKeepAlive(parentInstance!)!.getStorageContainer(),
         internals,
         parentInstance as any,
         null,