Procházet zdrojové kódy

chore(runtime-vapor): render fallback at the deepest invalid fragment (#14172)

edison před 4 měsíci
rodič
revize
e499d56307
1 změnil soubory, kde provedl 23 přidání a 17 odebrání
  1. 23 17
      packages/runtime-vapor/src/fragment.ts

+ 23 - 17
packages/runtime-vapor/src/fragment.ts

@@ -151,20 +151,31 @@ export class DynamicFragment extends VaporFragment {
     this.render(render, transition, parent, instance)
 
     if (this.fallback) {
-      // set fallback for nested fragments
-      const hasNestedFragment = isFragment(this.nodes)
-      if (hasNestedFragment) {
-        setFragmentFallback(this.nodes as VaporFragment, this.fallback)
+      // Find the deepest invalid fragment
+      let invalidFragment: VaporFragment | null = null
+      if (isFragment(this.nodes)) {
+        setFragmentFallback(
+          this.nodes,
+          this.fallback,
+          (frag: VaporFragment) => {
+            if (!isValidBlock(frag.nodes)) {
+              invalidFragment = frag
+            }
+          },
+        )
+      }
+
+      // Check self validity (when no nested fragment or nested is valid)
+      if (!invalidFragment && !isValidBlock(this.nodes)) {
+        invalidFragment = this
       }
 
-      const invalidFragment = findInvalidFragment(this)
       if (invalidFragment) {
         parent && remove(this.nodes, parent)
         const scope = this.scope || (this.scope = new EffectScope())
         scope.run(() => {
-          // for nested fragments, render invalid fragment's fallback
-          if (hasNestedFragment) {
-            renderFragmentFallback(invalidFragment)
+          if (invalidFragment !== this) {
+            renderFragmentFallback(invalidFragment!)
           } else {
             this.nodes = this.fallback!() || []
           }
@@ -297,6 +308,7 @@ export class DynamicFragment extends VaporFragment {
 export function setFragmentFallback(
   fragment: VaporFragment,
   fallback: BlockFn,
+  onFragment?: (frag: VaporFragment) => void,
 ): void {
   if (fragment.fallback) {
     const originalFallback = fragment.fallback
@@ -313,8 +325,10 @@ export function setFragmentFallback(
     fragment.fallback = fallback
   }
 
+  if (onFragment) onFragment(fragment)
+
   if (isFragment(fragment.nodes)) {
-    setFragmentFallback(fragment.nodes, fragment.fallback)
+    setFragmentFallback(fragment.nodes, fragment.fallback, onFragment)
   }
 }
 
@@ -328,14 +342,6 @@ function renderFragmentFallback(fragment: VaporFragment): void {
   }
 }
 
-function findInvalidFragment(fragment: VaporFragment): VaporFragment | null {
-  if (isValidBlock(fragment.nodes)) return null
-
-  return isFragment(fragment.nodes)
-    ? findInvalidFragment(fragment.nodes) || fragment
-    : fragment
-}
-
 export function isFragment(val: NonNullable<unknown>): val is VaporFragment {
   return val instanceof VaporFragment
 }