Skip to content

Commit eb848a6

Browse files
committed
feat(v-model): warn when v-model is bound on non-existant key
Warn when v-model is bound to a non-existant key since that key will not be reactive. Fixes vuejs#5932
1 parent 94512f3 commit eb848a6

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

src/compiler/codegen/index.js

+15
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,16 @@ function genDirectives (el: ASTElement, state: CodegenState): string | void {
291291
needRuntime = !!gen(el, dir, state.warn)
292292
}
293293
if (needRuntime) {
294+
let warning
294295
hasRuntime = true
295296
res += `{name:"${dir.name}",rawName:"${dir.rawName}"${
296297
dir.value ? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}` : ''
297298
}${
298299
dir.arg ? `,arg:"${dir.arg}"` : ''
299300
}${
300301
dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : ''
302+
}${
303+
process.env.NODE_ENV !== 'production' && (warning = genValidateValue(dir.value)) ? `,warn:${warning}` : ''
301304
}},`
302305
}
303306
}
@@ -490,3 +493,15 @@ function transformSpecialNewlines (text: string): string {
490493
.replace(/\u2028/g, '\\u2028')
491494
.replace(/\u2029/g, '\\u2029')
492495
}
496+
497+
function genValidateValue (expr: string): string {
498+
const parts = expr.split('.')
499+
if (parts.length > 1) {
500+
const parent = parts.slice(0, -1).join('.')
501+
const last = parts[parts.length - 1]
502+
if (last.indexOf('[') < 0) {
503+
return `!('${last}' in ${parent}) ? 'You are binding v-model to a key that does not exist, expression: ${expr}' : ''`
504+
}
505+
}
506+
return ''
507+
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export default {
4141
}
4242
}
4343
}
44+
45+
if (process.env.NODE_ENV !== 'production' && 'warn' in binding) {
46+
warn(binding.warn)
47+
}
4448
},
4549
componentUpdated (el, binding, vnode) {
4650
if (vnode.tag === 'select') {

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

+14
Original file line numberDiff line numberDiff line change
@@ -354,5 +354,19 @@ describe('Directive v-model text', () => {
354354
done()
355355
}, 16)
356356
})
357+
358+
it('warn binding v-model to non-existant data property', () => {
359+
new Vue({
360+
data: {
361+
testData: {}
362+
},
363+
template: `
364+
<div>
365+
<input v-model="testData.missingKey">
366+
</div>
367+
`
368+
}).$mount()
369+
expect('You are binding v-model to a key that does not exist, expression: testData.missingKey').toHaveBeenWarned()
370+
})
357371
}
358372
})

0 commit comments

Comments
 (0)