Переглянути джерело

fix(ssr): hydration for transition wrapper components with empty slot content (#5995)

fix #5991
小刘(liulinboyi) 3 роки тому
батько
коміт
eb22a62798

+ 1 - 1
packages/compiler-ssr/__tests__/ssrSlotOutlet.spec.ts

@@ -123,7 +123,7 @@ describe('ssr: <slot>', () => {
       "const { ssrRenderSlotInner: _ssrRenderSlotInner } = require(\\"vue/server-renderer\\")
 
       return function ssrRender(_ctx, _push, _parent, _attrs) {
-        _ssrRenderSlotInner(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
+        _ssrRenderSlotInner(_ctx.$slots, \\"default\\", {}, null, _push, _parent, null, true)
       }"
     `)
   })

+ 4 - 0
packages/compiler-ssr/src/transforms/ssrTransformSlotOutlet.ts

@@ -50,6 +50,10 @@ export const ssrTransformSlotOutlet: NodeTransform = (node, context) => {
       parent.children.filter(c => c.type === NodeTypes.ELEMENT).length === 1
     ) {
       method = SSR_RENDER_SLOT_INNER
+      if (!(context.scopeId && context.slotted !== false)) {
+        args.push('null')
+      }
+      args.push('true')
     }
 
     node.ssrCodegenNode = createCallExpression(context.helper(method), args)

+ 28 - 0
packages/server-renderer/__tests__/ssrSlot.spec.ts

@@ -113,4 +113,32 @@ describe('ssr: slot', () => {
       `<div><!--[--><!--[--><div>one</div><div>two</div><!--]--><!--]--></div>`
     )
   })
+
+  test('transition slot', async () => {
+    expect(
+      await renderToString(
+        createApp({
+          components: {
+            one: {
+              template: `<transition><slot/></transition>`
+            }
+          },
+          template: `<one><div v-if="false">foo</div></one>`
+        })
+      )
+    ).toBe(`<!---->`)
+
+    expect(
+      await renderToString(
+        createApp({
+          components: {
+            one: {
+              template: `<transition><slot/></transition>`
+            }
+          },
+          template: `<one><div v-if="true">foo</div></one>`
+        })
+      )
+    ).toBe(`<div>foo</div>`)
+  })
 })

+ 10 - 5
packages/server-renderer/src/helpers/ssrRenderSlot.ts

@@ -40,7 +40,8 @@ export function ssrRenderSlotInner(
   fallbackRenderFn: (() => void) | null,
   push: PushFn,
   parentComponent: ComponentInternalInstance,
-  slotScopeId?: string
+  slotScopeId?: string,
+  transition?: boolean
 ) {
   const slotFn = slots[slotName]
   if (slotFn) {
@@ -61,10 +62,14 @@ export function ssrRenderSlotInner(
       // ssr slot.
       // check if the slot renders all comments, in which case use the fallback
       let isEmptySlot = true
-      for (let i = 0; i < slotBuffer.length; i++) {
-        if (!isComment(slotBuffer[i])) {
-          isEmptySlot = false
-          break
+      if (transition) {
+        isEmptySlot = false
+      } else {
+        for (let i = 0; i < slotBuffer.length; i++) {
+          if (!isComment(slotBuffer[i])) {
+            isEmptySlot = false
+            break
+          }
         }
       }
       if (isEmptySlot) {