diff --git a/src/platforms/web/compiler/directives/model.js b/src/platforms/web/compiler/directives/model.js
index 98d4259cf98..3ae0e75b27a 100644
--- a/src/platforms/web/compiler/directives/model.js
+++ b/src/platforms/web/compiler/directives/model.js
@@ -21,6 +21,7 @@ export default function model (
const modifiers = dir.modifiers
const tag = el.tag
const type = el.attrsMap.type
+ const attrsMap = el.attrsMap
if (process.env.NODE_ENV !== 'production') {
// inputs with type="file" are read only and setting the input's
@@ -31,6 +32,20 @@ export default function model (
`File inputs are read only. Use a v-on:change listener instead.`
)
}
+
+ // warn if v-bind:value conflicts with v-model
+ if (
+ (attrsMap['v-bind:value'] || attrsMap[':value']) &&
+ type !== 'checkbox' &&
+ type !== 'radio' &&
+ tag !== 'select'
+ ) {
+ const vBindValue = attrsMap['v-bind:value'] ? 'v-bind:value' : ':value'
+ warn(
+ `${vBindValue} conflicts with v-model on the same element ` +
+ 'because the latter already expands to a value binding internally'
+ )
+ }
}
if (el.component) {
diff --git a/test/unit/features/directives/model-text.spec.js b/test/unit/features/directives/model-text.spec.js
index 7e291356c2f..2c186cc16f4 100644
--- a/test/unit/features/directives/model-text.spec.js
+++ b/test/unit/features/directives/model-text.spec.js
@@ -250,6 +250,32 @@ describe('Directive v-model text', () => {
expect('You are binding v-model directly to a v-for iteration alias').toHaveBeenWarned()
})
+ it('warn if v-model and v-bind:value conflict', () => {
+ new Vue({
+ data: {
+ test: 'foo'
+ },
+ template: ''
+ }).$mount()
+ expect(
+ 'v-bind:value conflicts with v-model on the same element because the latter already ' +
+ 'expands to a value binding internally'
+ ).toHaveBeenWarned()
+ })
+
+ it('warn if v-model and :value conflict', () => {
+ new Vue({
+ data: {
+ test: 'foo'
+ },
+ template: ''
+ }).$mount()
+ expect(
+ ':value conflicts with v-model on the same element because the latter already ' +
+ 'expands to a value binding internally'
+ ).toHaveBeenWarned()
+ })
+
if (!isAndroid) {
it('does not trigger extra input events with single compositionend', () => {
const spy = jasmine.createSpy()