]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(runtime-vapor): dynamic component fallback work with dynamic slots
authordaiwei <daiwei521@126.com>
Fri, 7 Nov 2025 07:12:20 +0000 (15:12 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 7 Nov 2025 07:12:20 +0000 (15:12 +0800)
packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts
packages/runtime-vapor/src/component.ts

index 89514e17701c7bf196b0f6957ceca59bbc3c3068..1ee50e78591eadd82babf6e462be9085981b55a9 100644 (file)
@@ -148,4 +148,35 @@ describe('api: createDynamicComponent', () => {
     await nextTick()
     expect(html()).toBe('<div><div>B</div><!--dynamic-component--></div>')
   })
+
+  test('fallback with dynamic slots', async () => {
+    const slotName = ref('default')
+    const { html } = define({
+      setup() {
+        return createDynamicComponent(() => 'div', null, {
+          $: [
+            () => ({
+              name: slotName.value,
+              fn: () => template('<span>hi</span>')(),
+            }),
+          ] as any,
+        })
+      },
+    }).render()
+
+    expect(html()).toBe(
+      '<div><span>hi</span><!--slot--></div><!--dynamic-component-->',
+    )
+
+    // update slot name
+    slotName.value = 'custom'
+    await nextTick()
+    expect(html()).toBe('<div><!--slot--></div><!--dynamic-component-->')
+
+    slotName.value = 'default'
+    await nextTick()
+    expect(html()).toBe(
+      '<div><span>hi</span><!--slot--></div><!--dynamic-component-->',
+    )
+  })
 })
index e850f08932df66f8cdc3683c18c2f17da32b51d7..10bd727d0df419f746d514154ab855a7c376c7f0 100644 (file)
@@ -665,7 +665,20 @@ export function createComponentWithFallback(
       setCurrentHydrationNode(el.firstChild)
     }
     if (rawSlots.$) {
-      // TODO dynamic slot fragment
+      const frag =
+        isHydrating || __DEV__
+          ? new DynamicFragment('slot')
+          : new DynamicFragment()
+
+      renderEffect(() => frag.update(getSlot(rawSlots as RawSlots, 'default')))
+
+      if (!isHydrating) {
+        const scopeId = currentInstance!.type.__scopeId
+        if (scopeId) setScopeId(frag, [`${scopeId}-s`])
+        insert(frag, el)
+      } else {
+        frag.hydrate()
+      }
     } else {
       insert(getSlot(rawSlots as RawSlots, 'default')!(), el)
     }