Skip to content

Commit abc4649

Browse files
committed
fix: prioritize v-model over value
1 parent 67ad861 commit abc4649

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

packages/compiler-ssr/__tests__/ssrVModel.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,24 @@ describe('ssr: v-model', () => {
9898
}"
9999
`)
100100

101+
expect(
102+
compileWithWrapper(
103+
`<select v-model="model" value="2"><option value="1"></option></select>`,
104+
).code,
105+
).toMatchInlineSnapshot(`
106+
"const { ssrIncludeBooleanAttr: _ssrIncludeBooleanAttr, ssrLooseContain: _ssrLooseContain, ssrLooseEqual: _ssrLooseEqual, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
107+
108+
return function ssrRender(_ctx, _push, _parent, _attrs) {
109+
_push(\`<div\${
110+
_ssrRenderAttrs(_attrs)
111+
}><select><option value="1"\${
112+
(_ssrIncludeBooleanAttr((Array.isArray(_ctx.model))
113+
? _ssrLooseContain(_ctx.model, "1")
114+
: _ssrLooseEqual(_ctx.model, "1"))) ? " selected" : ""
115+
}></option></select></div>\`)
116+
}"
117+
`)
118+
101119
expect(
102120
compileWithWrapper(
103121
`<select multiple v-model="model"><option value="1" selected></option><option value="2"></option></select>`,

packages/compiler-ssr/src/transforms/ssrTransformElement.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
8282
const needTagForRuntime =
8383
node.tag === 'textarea' || node.tag.indexOf('-') > 0
8484

85+
const hasVModel = node.props.some(
86+
p => p.type === NodeTypes.DIRECTIVE && p.name === 'model',
87+
)
88+
8589
// v-bind="obj", v-bind:[key] and custom directives can potentially
8690
// overwrite other static attrs and can affect final rendering result,
8791
// so when they are present we need to bail out to full `renderAttrs`
@@ -141,21 +145,24 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
141145
)
142146
}
143147
} else if (node.tag === 'select') {
144-
// <select> with dynamic v-bind. We don't know if the final props
145-
// will contain .value, so we will have to do something special:
146-
// assign the merged props to a temp variable, and check whether
147-
// it contains value (if yes, mark options selected).
148-
const tempId = `_temp${context.temps++}`
149-
propsExp.arguments = [
150-
createAssignmentExpression(
151-
createSimpleExpression(tempId, false),
152-
mergedProps,
153-
),
154-
]
155-
processSelectChildren(context, node.children, {
156-
type: 'dynamicVBind',
157-
tempId,
158-
})
148+
// v-model takes priority over value
149+
if (!hasVModel) {
150+
// <select> with dynamic v-bind. We don't know if the final props
151+
// will contain .value, so we will have to do something special:
152+
// assign the merged props to a temp variable, and check whether
153+
// it contains value (if yes, mark options selected).
154+
const tempId = `_temp${context.temps++}`
155+
propsExp.arguments = [
156+
createAssignmentExpression(
157+
createSimpleExpression(tempId, false),
158+
mergedProps,
159+
),
160+
]
161+
processSelectChildren(context, node.children, {
162+
type: 'dynamicVBind',
163+
tempId,
164+
})
165+
}
159166
} else if (node.tag === 'input') {
160167
// <input v-bind="obj" v-model>
161168
// we need to determine the props to render for the dynamic v-model
@@ -245,7 +252,7 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
245252
node.children = [createInterpolation(prop.exp, prop.loc)]
246253
}
247254
} else if (isTagWithValueBind(node, 'select', prop) && prop.exp) {
248-
if (!needMergeProps) {
255+
if (!needMergeProps && !hasVModel) {
249256
processSelectChildren(context, node.children, {
250257
type: 'dynamicValue',
251258
value: prop.exp,
@@ -351,7 +358,7 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
351358
if (node.tag === 'textarea' && name === 'value' && prop.value) {
352359
rawChildrenMap.set(node, escapeHtml(prop.value.content))
353360
} else if (node.tag === 'select' && name === 'value' && prop.value) {
354-
if (!needMergeProps) {
361+
if (!needMergeProps && !hasVModel) {
355362
processSelectChildren(context, node.children, {
356363
type: 'staticValue',
357364
value: prop.value.content,

0 commit comments

Comments
 (0)