Bladeren bron

fix(runtime-vapor): initialize hydrated vdom slot mount targets

daiwei 4 weken geleden
bovenliggende
commit
2f7d9dd2fa
2 gewijzigde bestanden met toevoegingen van 81 en 0 verwijderingen
  1. 79 0
      packages/runtime-vapor/__tests__/hydration.spec.ts
  2. 2 0
      packages/runtime-vapor/src/vdomInterop.ts

+ 79 - 0
packages/runtime-vapor/__tests__/hydration.spec.ts

@@ -6921,6 +6921,85 @@ describe('VDOM interop', () => {
     )
   })
 
+  test('hydrate VDOM slot content can mount after hydrating as empty', async () => {
+    const data = reactive({
+      show: false,
+      text: 'foo',
+    })
+    const { container } = await testWithVDOMApp(
+      `<script setup>
+        const data = _data
+        const components = _components
+      </script>
+      <template>
+        <components.VaporChild>
+          <template v-if="data.show">
+            <span>{{ data.text }}</span>
+          </template>
+        </components.VaporChild>
+      </template>`,
+      {
+        VaporChild: {
+          code: `<template><slot /></template>`,
+          vapor: true,
+        },
+      },
+      data,
+    )
+
+    expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+
+    data.show = true
+    await nextTick()
+    expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(
+      `
+      "
+      <!--[--><span>foo</span><!--]-->
+      "
+    `,
+    )
+  })
+
+  test('hydrate VDOM slot multi-root content can mount after hydrating as empty', async () => {
+    const data = reactive({
+      show: false,
+      text: 'foo',
+    })
+    const { container } = await testWithVDOMApp(
+      `<script setup>
+          const data = _data
+          const components = _components
+        </script>
+        <template>
+          <components.VaporChild>
+            <template v-if="data.show">
+              <span>{{ data.text }}</span>
+              <span>{{ data.text }}</span>
+            </template>
+          </components.VaporChild>
+        </template>`,
+      {
+        VaporChild: {
+          code: `<template><slot /></template>`,
+          vapor: true,
+        },
+      },
+      data,
+    )
+
+    expect(`Hydration node mismatch`).not.toHaveBeenWarned()
+
+    data.show = true
+    await nextTick()
+    expect(formatHtml(container.innerHTML)).toMatchInlineSnapshot(
+      `
+        "
+        <!--[--><span>foo</span><span>foo</span><!--]-->
+        "
+      `,
+    )
+  })
+
   test('hydrate interop vapor slot fallback', async () => {
     const data = reactive({
       text: 'foo',

+ 2 - 0
packages/runtime-vapor/src/vdomInterop.ts

@@ -1152,6 +1152,8 @@ function renderVDOMSlot(
   frag.hydrate = () => {
     if (!isHydrating) return
     scope.run(render)
+    currentParentNode = currentHydrationNode!.parentNode as ParentNode
+    currentAnchor = currentHydrationNode
     isMounted = true
   }