Skip to content

Commit e9bf5d1

Browse files
committed
add warning for using v-model on v-for alias
1 parent 32383e5 commit e9bf5d1

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

src/compiler/parser/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,9 @@ function processAttrs (el) {
388388
name = name.slice(0, -(arg.length + 1))
389389
}
390390
addDirective(el, name, value, arg, modifiers)
391+
if (process.env.NODE_ENV !== 'production' && name === 'model') {
392+
checkForAliasModel(el, value)
393+
}
391394
}
392395
} else {
393396
// literal attribute
@@ -469,3 +472,19 @@ function guardIESVGBug (attrs) {
469472
}
470473
return res
471474
}
475+
476+
function checkForAliasModel (el, value) {
477+
let _el = el
478+
while (_el) {
479+
if (_el.for && _el.alias === value) {
480+
warn(
481+
`<${el.tag} v-model="${value}">: ` +
482+
`You are binding v-model directly to a v-for iteration alias. ` +
483+
`This will not be able to modify the v-for source array because ` +
484+
`writing to the alias is like modifying a function local variable. ` +
485+
`Consider using an array of objects and use v-model on an object property instead.`
486+
)
487+
}
488+
_el = _el.parent
489+
}
490+
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,20 @@ describe('Directive v-model text', () => {
160160
triggerEvent(vm.$el, 'input')
161161
expect(spy).toHaveBeenCalledWith('b')
162162
})
163+
164+
it('warn binding to v-for alias', () => {
165+
new Vue({
166+
data: {
167+
strings: ['hi']
168+
},
169+
template: `
170+
<div>
171+
<div v-for="str in strings">
172+
<input v-model="str">
173+
</div>
174+
</div>
175+
`
176+
}).$mount()
177+
expect('You are binding v-model directly to a v-for iteration alias').toHaveBeenWarned()
178+
})
163179
})

0 commit comments

Comments
 (0)