fix(compiler-ssr): handle v-model checkbox with true-value binding
This commit is contained in:
parent
48f00c0f1b
commit
fe5428db12
@ -49,7 +49,7 @@ describe('ssr: v-model', () => {
|
|||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<input type="checkbox"', () => {
|
test('<input type="checkbox">', () => {
|
||||||
expect(compileWithWrapper(`<input type="checkbox" v-model="bar">`).code)
|
expect(compileWithWrapper(`<input type="checkbox" v-model="bar">`).code)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
"const { ssrLooseContain: _ssrLooseContain, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
"const { ssrLooseContain: _ssrLooseContain, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
@ -81,6 +81,38 @@ describe('ssr: v-model', () => {
|
|||||||
}></div>\`)
|
}></div>\`)
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(
|
||||||
|
`<input type="checkbox" :true-value="foo" :false-value="bar" v-model="baz">`
|
||||||
|
).code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input type=\\"checkbox\\"\${
|
||||||
|
(_ssrLooseEqual(_ctx.baz, _ctx.foo)) ? \\" checked\\" : \\"\\"
|
||||||
|
}></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(
|
||||||
|
compileWithWrapper(
|
||||||
|
`<input type="checkbox" true-value="foo" false-value="bar" v-model="baz">`
|
||||||
|
).code
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
"const { ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require(\\"@vue/server-renderer\\")
|
||||||
|
|
||||||
|
return function ssrRender(_ctx, _push, _parent, _attrs) {
|
||||||
|
_push(\`<div\${
|
||||||
|
_ssrRenderAttrs(_attrs)
|
||||||
|
}><input type=\\"checkbox\\"\${
|
||||||
|
(_ssrLooseEqual(_ctx.baz, \\"foo\\")) ? \\" checked\\" : \\"\\"
|
||||||
|
}></div>\`)
|
||||||
|
}"
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('<textarea>', () => {
|
test('<textarea>', () => {
|
||||||
|
@ -25,7 +25,8 @@ import {
|
|||||||
isBindKey,
|
isBindKey,
|
||||||
createSequenceExpression,
|
createSequenceExpression,
|
||||||
InterpolationNode,
|
InterpolationNode,
|
||||||
isStaticExp
|
isStaticExp,
|
||||||
|
AttributeNode
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import {
|
import {
|
||||||
escapeHtml,
|
escapeHtml,
|
||||||
@ -159,6 +160,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
|||||||
|
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const prop = node.props[i]
|
const prop = node.props[i]
|
||||||
|
// ignore true-value/false-value on input
|
||||||
|
if (node.tag === 'input' && isTrueFalseValue(prop)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// special cases with children override
|
// special cases with children override
|
||||||
if (prop.type === NodeTypes.DIRECTIVE) {
|
if (prop.type === NodeTypes.DIRECTIVE) {
|
||||||
if (prop.name === 'html' && prop.exp) {
|
if (prop.name === 'html' && prop.exp) {
|
||||||
@ -306,6 +311,19 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTrueFalseValue(prop: DirectiveNode | AttributeNode) {
|
||||||
|
if (prop.type === NodeTypes.DIRECTIVE) {
|
||||||
|
return (
|
||||||
|
prop.name === 'bind' &&
|
||||||
|
prop.arg &&
|
||||||
|
isStaticExp(prop.arg) &&
|
||||||
|
(prop.arg.content === 'true-value' || prop.arg.content === 'false-value')
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return prop.name === 'true-value' || prop.name === 'false-value'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isTextareaWithValue(
|
function isTextareaWithValue(
|
||||||
node: PlainElementNode,
|
node: PlainElementNode,
|
||||||
prop: DirectiveNode
|
prop: DirectiveNode
|
||||||
|
@ -71,19 +71,36 @@ export const ssrTransformModel: DirectiveTransform = (dir, node, context) => {
|
|||||||
]
|
]
|
||||||
break
|
break
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
res.props = [
|
const trueValueBinding = findProp(node, 'true-value')
|
||||||
createObjectProperty(
|
if (trueValueBinding) {
|
||||||
`checked`,
|
const trueValue =
|
||||||
createConditionalExpression(
|
trueValueBinding.type === NodeTypes.ATTRIBUTE
|
||||||
createCallExpression(`Array.isArray`, [model]),
|
? JSON.stringify(trueValueBinding.value!.content)
|
||||||
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
|
: trueValueBinding.exp!
|
||||||
|
res.props = [
|
||||||
|
createObjectProperty(
|
||||||
|
`checked`,
|
||||||
|
createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
|
||||||
model,
|
model,
|
||||||
value
|
trueValue
|
||||||
]),
|
])
|
||||||
model
|
|
||||||
)
|
)
|
||||||
)
|
]
|
||||||
]
|
} else {
|
||||||
|
res.props = [
|
||||||
|
createObjectProperty(
|
||||||
|
`checked`,
|
||||||
|
createConditionalExpression(
|
||||||
|
createCallExpression(`Array.isArray`, [model]),
|
||||||
|
createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
|
||||||
|
model,
|
||||||
|
value
|
||||||
|
]),
|
||||||
|
model
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case 'file':
|
case 'file':
|
||||||
context.onError(
|
context.onError(
|
||||||
|
Loading…
Reference in New Issue
Block a user