Browse Source

fix(compiler-ssr): should pass necessary tag names for dynamic v-bind

Evan You 6 years ago
parent
commit
a46f3b354d

+ 15 - 1
packages/compiler-ssr/__tests__/ssrElement.spec.ts

@@ -57,13 +57,27 @@ describe('ssr: element', () => {
           let _temp0
 
           _push(\`<textarea\${
-            _ssrRenderAttrs(_temp0 = _ctx.obj)
+            _ssrRenderAttrs(_temp0 = _ctx.obj, \\"textarea\\")
           }>\${
             _ssrInterpolate((\\"value\\" in _temp0) ? _temp0.value : \\"fallback\\")
           }</textarea>\`)
         }"
       `)
     })
+
+    test('should pass tag to custom elements w/ dynamic v-bind', () => {
+      expect(
+        compile(`<my-foo v-bind="obj"></my-foo>`, {
+          isCustomElement: () => true
+        }).code
+      ).toMatchInlineSnapshot(`
+        "const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
+
+        return function ssrRender(_ctx, _push, _parent) {
+          _push(\`<my-foo\${_ssrRenderAttrs(_ctx.obj, \\"my-foo\\")}></my-foo>\`)
+        }"
+      `)
+    })
   })
 
   describe('attrs', () => {

+ 18 - 5
packages/compiler-ssr/src/transforms/ssrTransformElement.ts

@@ -60,6 +60,9 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
       // element
       // generate the template literal representing the open tag.
       const openTag: TemplateLiteral['elements'] = [`<${node.tag}`]
+      // some tags need to be pasesd to runtime for special checks
+      const needTagForRuntime =
+        node.tag === 'textarea' || node.tag.indexOf('-') > 0
 
       // v-bind="obj" or v-bind:[key] can potentially overwrite other static
       // attrs and can affect final rendering result, so when they are present
@@ -79,10 +82,12 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
             // assign the merged props to a temp variable, and check whether
             // it contains value (if yes, render is as children).
             const tempId = `_temp${context.temps++}`
-            propsExp.arguments[0] = createAssignmentExpression(
-              createSimpleExpression(tempId, false),
-              props
-            )
+            propsExp.arguments = [
+              createAssignmentExpression(
+                createSimpleExpression(tempId, false),
+                props
+              )
+            ]
             const existingText = node.children[0] as TextNode | undefined
             rawChildrenMap.set(
               node,
@@ -125,6 +130,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
             }
           }
 
+          if (needTagForRuntime) {
+            propsExp.arguments.push(`"${node.tag}"`)
+          }
+
           openTag.push(propsExp)
         }
       }
@@ -234,10 +243,14 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
                   // dynamic key attr
                   // this branch is only encountered for custom directive
                   // transforms that returns properties with dynamic keys
+                  const args: CallExpression['arguments'] = [key, value]
+                  if (needTagForRuntime) {
+                    args.push(`"${node.tag}"`)
+                  }
                   openTag.push(
                     createCallExpression(
                       context.helper(SSR_RENDER_DYNAMIC_ATTR),
-                      [key, value]
+                      args
                     )
                   )
                 }