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

This commit is contained in:
Evan You 2020-03-16 18:24:26 -04:00
parent 3b40fc56db
commit a46f3b354d
2 changed files with 33 additions and 6 deletions

View File

@ -57,13 +57,27 @@ describe('ssr: element', () => {
let _temp0 let _temp0
_push(\`<textarea\${ _push(\`<textarea\${
_ssrRenderAttrs(_temp0 = _ctx.obj) _ssrRenderAttrs(_temp0 = _ctx.obj, \\"textarea\\")
}>\${ }>\${
_ssrInterpolate((\\"value\\" in _temp0) ? _temp0.value : \\"fallback\\") _ssrInterpolate((\\"value\\" in _temp0) ? _temp0.value : \\"fallback\\")
}</textarea>\`) }</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', () => { describe('attrs', () => {

View File

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