소스 검색

fix(ssr): fix hydration error for slot outlet inside transition-group (#9937)

close #9933
edison 2 년 전
부모
커밋
6cb00ed0f9
2개의 변경된 파일23개의 추가작업 그리고 3개의 파일을 삭제
  1. 16 0
      packages/compiler-ssr/__tests__/ssrSlotOutlet.spec.ts
  2. 7 3
      packages/compiler-ssr/src/transforms/ssrTransformSlotOutlet.ts

+ 16 - 0
packages/compiler-ssr/__tests__/ssrSlotOutlet.spec.ts

@@ -127,4 +127,20 @@ describe('ssr: <slot>', () => {
       }"
     `)
   })
+
+  test('inside transition-group', () => {
+    const { code } = compile(
+      `<TransitionGroup tag="div"><slot/></TransitionGroup>`,
+    )
+    expect(code).toMatch(ssrHelpers[SSR_RENDER_SLOT_INNER])
+    expect(code).toMatchInlineSnapshot(`
+      "const { ssrRenderSlotInner: _ssrRenderSlotInner, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
+
+      return function ssrRender(_ctx, _push, _parent, _attrs) {
+        _push(\`<div\${_ssrRenderAttrs(_attrs)}>\`)
+        _ssrRenderSlotInner(_ctx.$slots, "default", {}, null, _push, _parent, null, true)
+        _push(\`</div>\`)
+      }"
+    `)
+  })
 })

+ 7 - 3
packages/compiler-ssr/src/transforms/ssrTransformSlotOutlet.ts

@@ -4,6 +4,7 @@ import {
   NodeTypes,
   type SlotOutletNode,
   TRANSITION,
+  TRANSITION_GROUP,
   createCallExpression,
   createFunctionExpression,
   isSlotOutlet,
@@ -37,16 +38,19 @@ export const ssrTransformSlotOutlet: NodeTransform = (node, context) => {
 
     let method = SSR_RENDER_SLOT
 
-    // #3989
+    // #3989, #9933
     // check if this is a single slot inside a transition wrapper - since
-    // transition will unwrap the slot fragment into a single vnode at runtime,
+    // transition/transition-group will unwrap the slot fragment into vnode(s) at runtime,
     // we need to avoid rendering the slot as a fragment.
     const parent = context.parent
+    let componentType
     if (
       parent &&
       parent.type === NodeTypes.ELEMENT &&
       parent.tagType === ElementTypes.COMPONENT &&
-      resolveComponentType(parent, context, true) === TRANSITION &&
+      ((componentType = resolveComponentType(parent, context, true)) ===
+        TRANSITION ||
+        componentType === TRANSITION_GROUP) &&
       parent.children.filter(c => c.type === NodeTypes.ELEMENT).length === 1
     ) {
       method = SSR_RENDER_SLOT_INNER