Skip to content

Commit 90ea2eb

Browse files
yyx990803hefeng
authored and
hefeng
committed
fix: fix v-model :value warning on custom component
fix vuejs#7084
1 parent e95ee95 commit 90ea2eb

File tree

2 files changed

+38
-25
lines changed

2 files changed

+38
-25
lines changed

src/platforms/web/compiler/directives/model.js

+13-15
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ export default function model (
2121
const modifiers = dir.modifiers
2222
const tag = el.tag
2323
const type = el.attrsMap.type
24-
const attrsMap = el.attrsMap
2524

2625
if (process.env.NODE_ENV !== 'production') {
2726
// inputs with type="file" are read only and setting the input's
@@ -32,20 +31,6 @@ export default function model (
3231
`File inputs are read only. Use a v-on:change listener instead.`
3332
)
3433
}
35-
36-
// warn if v-bind:value conflicts with v-model
37-
if (
38-
(attrsMap['v-bind:value'] || attrsMap[':value']) &&
39-
type !== 'checkbox' &&
40-
type !== 'radio' &&
41-
tag !== 'select'
42-
) {
43-
const vBindValue = attrsMap['v-bind:value'] ? 'v-bind:value' : ':value'
44-
warn(
45-
`${vBindValue} conflicts with v-model on the same element ` +
46-
'because the latter already expands to a value binding internally'
47-
)
48-
}
4934
}
5035

5136
if (el.component) {
@@ -143,6 +128,19 @@ function genDefaultModel (
143128
modifiers: ?ASTModifiers
144129
): ?boolean {
145130
const type = el.attrsMap.type
131+
132+
// warn if v-bind:value conflicts with v-model
133+
if (process.env.NODE_ENV !== 'production') {
134+
const value = el.attrsMap['v-bind:value'] || el.attrsMap[':value']
135+
if (value) {
136+
const binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value'
137+
warn(
138+
`${binding}="${value}" conflicts with v-model on the same element ` +
139+
'because the latter already expands to a value binding internally'
140+
)
141+
}
142+
}
143+
146144
const { lazy, number, trim } = modifiers || {}
147145
const needCompositionGuard = !lazy && type !== 'range'
148146
const event = lazy

test/unit/features/directives/model-text.spec.js

+25-10
Original file line numberDiff line numberDiff line change
@@ -255,25 +255,40 @@ describe('Directive v-model text', () => {
255255
data: {
256256
test: 'foo'
257257
},
258-
template: '<input type="text" v-model="test" v-bind:value="test"/>'
258+
template: '<input type="text" v-model="test" v-bind:value="test">'
259259
}).$mount()
260-
expect(
261-
'v-bind:value conflicts with v-model on the same element because the latter already ' +
262-
'expands to a value binding internally'
263-
).toHaveBeenWarned()
260+
expect('v-bind:value="test" conflicts with v-model').toHaveBeenWarned()
264261
})
265262

266263
it('warn if v-model and :value conflict', () => {
267264
new Vue({
268265
data: {
269266
test: 'foo'
270267
},
271-
template: '<input type="text" v-model="test" :value="test"/>'
268+
template: '<input type="text" v-model="test" :value="test">'
272269
}).$mount()
273-
expect(
274-
':value conflicts with v-model on the same element because the latter already ' +
275-
'expands to a value binding internally'
276-
).toHaveBeenWarned()
270+
expect(':value="test" conflicts with v-model').toHaveBeenWarned()
271+
})
272+
273+
it('should not warn on radio, checkbox, or custom component', () => {
274+
new Vue({
275+
data: { test: '' },
276+
components: {
277+
foo: {
278+
props: ['model', 'value'],
279+
model: { prop: 'model', event: 'change' },
280+
template: `<div/>`
281+
}
282+
},
283+
template: `
284+
<div>
285+
<input type="checkbox" v-model="test" :value="test">
286+
<input type="radio" v-model="test" :value="test">
287+
<foo v-model="test" :value="test"/>
288+
</div>
289+
`
290+
}).$mount()
291+
expect('conflicts with v-model').not.toHaveBeenWarned()
277292
})
278293

279294
if (!isAndroid) {

0 commit comments

Comments
 (0)