mirror of https://github.com/vuejs/core.git
fix(compiler-ssr): fix ssr compile error for select with non-option children (#9442)
fix #9440
This commit is contained in:
parent
aacb66def4
commit
cdb2e725e7
|
@ -69,6 +69,57 @@ describe('ssr: v-model', () => {
|
||||||
}></option></select></div>\`)
|
}></option></select></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`<select multiple v-model="model"><slot/></select>`)
|
||||||
|
.code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderSlot: _ssrRenderSlot, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple>\`)
|
||||||
|
_ssrRenderSlot(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
|
||||||
|
_push(\`</select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`
|
||||||
|
<select multiple v-model="model">
|
||||||
|
<optgroup label="foo">
|
||||||
|
<option value="bar">bar</option>
|
||||||
|
</optgroup>
|
||||||
|
</select>`).code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><select multiple><optgroup label=\\"foo\\"><option value=\\"bar\\"\${
|
||||||
|
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
|
||||||
|
? _ssrLooseContain(_ctx.model, \\"bar\\")
|
||||||
|
: _ssrLooseEqual(_ctx.model, \\"bar\\"))) ? \\" selected\\" : \\"\\"
|
||||||
|
}>bar</option></optgroup></select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(`
|
||||||
|
<select multiple v-model="model">
|
||||||
|
<optgroup label="foo">
|
||||||
|
<slot/>
|
||||||
|
</optgroup>
|
||||||
|
</select>`).code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrRenderSlot: _ssrRenderSlot, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${_ssrRenderAttrs(_attrs)}><select multiple><optgroup label=\\"foo\\">\`)
|
||||||
|
_ssrRenderSlot(_ctx.$slots, \\"default\\", {}, null, _push, _parent)
|
||||||
|
_push(\`</optgroup></select></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input type="radio">', () => {
|
test('<input type="radio">', () => {
|
||||||
|
|
|
@ -38,6 +38,38 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processOption(plainNode: PlainElementNode) {
|
||||||
|
if (plainNode.tag === 'option') {
|
||||||
|
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
|
||||||
|
const value = findValueBinding(plainNode)
|
||||||
|
plainNode.ssrCodegenNode!.elements.push(
|
||||||
|
createConditionalExpression(
|
||||||
|
createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [
|
||||||
|
createConditionalExpression(
|
||||||
|
createCallExpression(`Array.isArray`, [model]),
|
||||||
|
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
|
||||||
|
model,
|
||||||
|
value
|
||||||
|
]),
|
||||||
|
createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
|
||||||
|
model,
|
||||||
|
value
|
||||||
|
])
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
createSimpleExpression(' selected', true),
|
||||||
|
createSimpleExpression('', true),
|
||||||
|
false /* no newline */
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (plainNode.tag === 'optgroup') {
|
||||||
|
plainNode.children.forEach(option =>
|
||||||
|
processOption(option as PlainElementNode)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (node.tagType === ElementTypes.ELEMENT) {
|
if (node.tagType === ElementTypes.ELEMENT) {
|
||||||
const res: DirectiveTransformResult = { props: [] }
|
const res: DirectiveTransformResult = { props: [] }
|
||||||
const defaultProps = [
|
const defaultProps = [
|
||||||
|
@ -130,32 +162,9 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
checkDuplicatedValue()
|
checkDuplicatedValue()
|
||||||
node.children = [createInterpolation(model, model.loc)]
|
node.children = [createInterpolation(model, model.loc)]
|
||||||
} else if (node.tag === 'select') {
|
} else if (node.tag === 'select') {
|
||||||
node.children.forEach(option => {
|
node.children.forEach(child => {
|
||||||
if (option.type === NodeTypes.ELEMENT) {
|
if (child.type === NodeTypes.ELEMENT) {
|
||||||
const plainNode = option as PlainElementNode
|
processOption(child as PlainElementNode)
|
||||||
if (plainNode.props.findIndex(p => p.name === 'selected') === -1) {
|
|
||||||
const value = findValueBinding(plainNode)
|
|
||||||
plainNode.ssrCodegenNode!.elements.push(
|
|
||||||
createConditionalExpression(
|
|
||||||
createCallExpression(context.helper(SSR_INCLUDE_BOOLEAN_ATTR), [
|
|
||||||
createConditionalExpression(
|
|
||||||
createCallExpression(`Array.isArray`, [model]),
|
|
||||||
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
|
|
||||||
model,
|
|
||||||
value
|
|
||||||
]),
|
|
||||||
createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
|
|
||||||
model,
|
|
||||||
value
|
|
||||||
])
|
|
||||||
)
|
|
||||||
]),
|
|
||||||
createSimpleExpression(' selected', true),
|
|
||||||
createSimpleExpression('', true),
|
|
||||||
false /* no newline */
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue