Jelajahi Sumber

fix(ssr): fix the bug that multi slot scope id does not work on component (#6100)

close #6093
mmis1000 1 tahun lalu
induk
melakukan
4c74302aae

+ 90 - 0
packages/server-renderer/__tests__/ssrScopeId.spec.ts

@@ -179,4 +179,94 @@ describe('ssr: scopedId runtime behavior', () => {
     const result = await renderToString(createApp(Comp)) // output: `<div></div>`
     expect(result).toBe(`<div parent></div>`)
   })
+
+  // #6093
+  test(':slotted on forwarded slots on component', async () => {
+    const Wrapper = {
+      __scopeId: 'wrapper',
+      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {
+        // <div class="wrapper"><slot/></div>
+        push(
+          `<div${ssrRenderAttrs(
+            mergeProps({ class: 'wrapper' }, attrs),
+          )} wrapper>`,
+        )
+        ssrRenderSlot(
+          ctx.$slots,
+          'default',
+          {},
+          null,
+          push,
+          parent,
+          'wrapper-s',
+        )
+        push(`</div>`)
+      },
+    }
+
+    const Slotted = {
+      __scopeId: 'slotted',
+      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {
+        // <Wrapper><slot/></Wrapper>
+        push(
+          ssrRenderComponent(
+            Wrapper,
+            attrs,
+            {
+              default: withCtx(
+                (_: any, push: any, parent: any, scopeId: string) => {
+                  ssrRenderSlot(
+                    ctx.$slots,
+                    'default',
+                    {},
+                    null,
+                    push,
+                    parent,
+                    'slotted-s' + scopeId,
+                  )
+                },
+              ),
+              _: 1,
+            } as any,
+            parent,
+          ),
+        )
+      },
+    }
+
+    const Child = {
+      ssrRender: (ctx: any, push: any, parent: any, attrs: any) => {
+        push(`<div${ssrRenderAttrs(attrs)}></div>`)
+      },
+    }
+
+    const Root = {
+      __scopeId: 'root',
+      // <Slotted><Child></Child></Slotted>
+      ssrRender: (_: any, push: any, parent: any, attrs: any) => {
+        push(
+          ssrRenderComponent(
+            Slotted,
+            attrs,
+            {
+              default: withCtx(
+                (_: any, push: any, parent: any, scopeId: string) => {
+                  push(ssrRenderComponent(Child, null, null, parent, scopeId))
+                },
+              ),
+              _: 1,
+            } as any,
+            parent,
+          ),
+        )
+      },
+    }
+
+    const result = await renderToString(createApp(Root))
+    expect(result).toBe(
+      `<div class="wrapper" root slotted wrapper>` +
+        `<!--[--><!--[--><div root slotted-s wrapper-s></div><!--]--><!--]-->` +
+        `</div>`,
+    )
+  })
 })

+ 4 - 1
packages/server-renderer/src/render.ts

@@ -181,7 +181,10 @@ function renderComponentSubTree(
 
       if (slotScopeId) {
         if (!hasCloned) attrs = { ...attrs }
-        attrs![slotScopeId.trim()] = ''
+        const slotScopeIdList = slotScopeId.trim().split(' ')
+        for (let i = 0; i < slotScopeIdList.length; i++) {
+          attrs![slotScopeIdList[i]] = ''
+        }
       }
 
       // set current rendering instance for asset resolution