Skip to content

Commit

Permalink
fix: fix v-model :value warning on custom component
Browse files Browse the repository at this point in the history
fix #7084
  • Loading branch information
yyx990803 committed Nov 18, 2017
1 parent 06f121b commit 59dea37
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 25 deletions.
28 changes: 13 additions & 15 deletions src/platforms/web/compiler/directives/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ 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
Expand All @@ -32,20 +31,6 @@ 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) {
Expand Down Expand Up @@ -143,6 +128,19 @@ function genDefaultModel (
modifiers: ?ASTModifiers
): ?boolean {
const type = el.attrsMap.type

// warn if v-bind:value conflicts with v-model
if (process.env.NODE_ENV !== 'production') {
const value = el.attrsMap['v-bind:value'] || el.attrsMap[':value']
if (value) {
const binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value'
warn(
`${binding}="${value}" conflicts with v-model on the same element ` +
'because the latter already expands to a value binding internally'
)
}
}

const { lazy, number, trim } = modifiers || {}
const needCompositionGuard = !lazy && type !== 'range'
const event = lazy
Expand Down
35 changes: 25 additions & 10 deletions test/unit/features/directives/model-text.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,25 +255,40 @@ describe('Directive v-model text', () => {
data: {
test: 'foo'
},
template: '<input type="text" v-model="test" v-bind:value="test"/>'
template: '<input type="text" v-model="test" v-bind:value="test">'
}).$mount()
expect(
'v-bind:value conflicts with v-model on the same element because the latter already ' +
'expands to a value binding internally'
).toHaveBeenWarned()
expect('v-bind:value="test" conflicts with v-model').toHaveBeenWarned()
})

it('warn if v-model and :value conflict', () => {
new Vue({
data: {
test: 'foo'
},
template: '<input type="text" v-model="test" :value="test"/>'
template: '<input type="text" v-model="test" :value="test">'
}).$mount()
expect(
':value conflicts with v-model on the same element because the latter already ' +
'expands to a value binding internally'
).toHaveBeenWarned()
expect(':value="test" conflicts with v-model').toHaveBeenWarned()
})

it('should not warn on radio, checkbox, or custom component', () => {
new Vue({
data: { test: '' },
components: {
foo: {
props: ['model', 'value'],
model: { prop: 'model', event: 'change' },
template: `<div/>`
}
},
template: `
<div>
<input type="checkbox" v-model="test" :value="test">
<input type="radio" v-model="test" :value="test">
<foo v-model="test" :value="test"/>
</div>
`
}).$mount()
expect('conflicts with v-model').not.toHaveBeenWarned()
})

if (!isAndroid) {
Expand Down

0 comments on commit 59dea37

Please sign in to comment.