]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: handling hydration edison/feat/dynamicComponentWithDynamicSlot 14064/head
authordaiwei <daiwei521@126.com>
Fri, 7 Nov 2025 07:58:40 +0000 (15:58 +0800)
committerdaiwei <daiwei521@126.com>
Fri, 7 Nov 2025 07:58:40 +0000 (15:58 +0800)
packages/runtime-vapor/__tests__/hydration.spec.ts
packages/runtime-vapor/src/component.ts

index 17174408eeea685ef7b2d640e2b8f9136762c2c4..7094a0f60af7f6e19df41d4616f08c6db6907d7a 100644 (file)
@@ -1065,6 +1065,34 @@ describe('Vapor Mode hydration', () => {
       `,
       )
     })
+
+    test('dynamic component fallback with dynamic slots', async () => {
+      const data = ref({
+        name: 'default',
+        msg: 'foo',
+      })
+      const { container } = await testHydration(
+        `<template>
+          <component :is="'div'">
+            <template v-slot:[data.name]>
+              <span>{{ data.msg }}</span>
+            </template>
+          </component>
+        </template>`,
+        {},
+        data,
+      )
+
+      expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(
+        `"<div><span>foo</span><!----></div><!--dynamic-component-->"`,
+      )
+
+      data.value.msg = 'bar'
+      await nextTick()
+      expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(
+        `"<div><span>bar</span><!----></div><!--dynamic-component-->"`,
+      )
+    })
   })
 
   describe('if', () => {
index 10bd727d0df419f746d514154ab855a7c376c7f0..d083d7404cbdf8f197882e4d37b93140bc081fc7 100644 (file)
@@ -665,22 +665,16 @@ export function createComponentWithFallback(
       setCurrentHydrationNode(el.firstChild)
     }
     if (rawSlots.$) {
-      const frag =
-        isHydrating || __DEV__
-          ? new DynamicFragment('slot')
-          : new DynamicFragment()
-
+      // ssr output does not contain the slot anchor, use an empty string
+      // as the anchor label to avoid slot anchor search errors
+      const frag = new DynamicFragment(
+        isHydrating ? '' : __DEV__ ? 'slot' : undefined,
+      )
       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()
-      }
+      if (!isHydrating) insert(frag, el)
     } else {
-      insert(getSlot(rawSlots as RawSlots, 'default')!(), el)
+      const block = getSlot(rawSlots as RawSlots, 'default')!()
+      if (!isHydrating) insert(block, el)
     }
     if (isHydrating) {
       setCurrentHydrationNode(nextNode)