Browse Source

fix(compiler-ssr): fix SSR issue when dynamic and static class co-exist (#2354)

Mathieu TUDISCO 5 years ago
parent
commit
8539c0bf32

+ 9 - 0
packages/compiler-ssr/__tests__/ssrElement.spec.ts

@@ -112,6 +112,15 @@ describe('ssr: element', () => {
       `)
     })
 
+    test('v-bind:class + static class', () => {
+      expect(getCompiledString(`<div :class="bar" class="foo"></div>`))
+        .toMatchInlineSnapshot(`
+        "\`<div class=\\"\${
+            _ssrRenderClass([_ctx.bar, \\"foo\\"])
+          }\\"></div>\`"
+      `)
+    })
+
     test('v-bind:style', () => {
       expect(getCompiledString(`<div id="foo" :style="bar"></div>`))
         .toMatchInlineSnapshot(`

+ 2 - 2
packages/compiler-ssr/src/transforms/ssrInjectCssVars.ts

@@ -15,8 +15,8 @@ export const ssrInjectCssVars: NodeTransform = (node, context) => {
     return
   }
 
-  // _cssVars is initailized once per render function
-  // the code is injected in ssrCodegenTrasnform when creating the
+  // _cssVars is initialized once per render function
+  // the code is injected in ssrCodegenTransform when creating the
   // ssr transform context
   if (node.type === NodeTypes.ROOT) {
     context.identifiers._cssVars = 1

+ 4 - 3
packages/compiler-ssr/src/transforms/ssrTransformElement.ts

@@ -324,9 +324,10 @@ function removeStaticBinding(
   tag: TemplateLiteral['elements'],
   binding: string
 ) {
-  const i = tag.findIndex(
-    e => typeof e === 'string' && e.startsWith(` ${binding}=`)
-  )
+  const regExp = new RegExp(`^ ${binding}=".+"$`)
+
+  const i = tag.findIndex(e => typeof e === 'string' && regExp.test(e))
+
   if (i > -1) {
     tag.splice(i, 1)
   }

+ 18 - 0
packages/server-renderer/__tests__/renderToString.spec.ts

@@ -142,6 +142,24 @@ describe('ssr: renderToString', () => {
       )
     })
 
+    test('template components with dynamic class attribute after static', async () => {
+      const app = createApp({
+        template: `<div><div class="child" :class="'dynamic'"></div></div>`
+      })
+      expect(await renderToString(app)).toBe(
+        `<div><div class="dynamic child"></div></div>`
+      )
+    })
+
+    test('template components with dynamic class attribute before static', async () => {
+      const app = createApp({
+        template: `<div><div :class="'dynamic'" class="child"></div></div>`
+      })
+      expect(await renderToString(app)).toBe(
+        `<div><div class="dynamic child"></div></div>`
+      )
+    })
+
     test('mixing optimized / vnode / template components', async () => {
       const OptimizedChild = {
         props: ['msg'],