Skip to content

Commit 5ae63d9

Browse files
committed
warn v-for component lists without explicit keys
1 parent f33ca99 commit 5ae63d9

File tree

8 files changed

+33
-8
lines changed

8 files changed

+33
-8
lines changed

src/compiler/codegen/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,18 @@ function genFor (el: any): string {
144144
const alias = el.alias
145145
const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
146146
const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
147+
148+
if (
149+
process.env.NODE_ENV !== 'production' &&
150+
maybeComponent(el) && el.tag !== 'slot' && el.tag !== 'template' && !el.key
151+
) {
152+
warn(
153+
`<${el.tag} v-for="${alias} in ${exp}">: component lists rendered with ` +
154+
`v-for should have explicit keys. ` +
155+
`See https://vuejs.org/guide/list.html#key for more info.`
156+
)
157+
}
158+
147159
el.forProcessed = true // avoid recursion
148160
return `_l((${exp}),` +
149161
`function(${alias}${iterator1}${iterator2}){` +

src/compiler/helpers.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { parseFilters } from './parser/filter-parser'
44

55
export function baseWarn (msg: string) {
6-
console.error(`[Vue parser]: ${msg}`)
6+
console.error(`[Vue compiler]: ${msg}`)
77
}
88

99
export function pluckModuleFunction<F: Function> (

src/entries/web-runtime-with-compiler.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Vue.prototype.$mount = function (
5555
}
5656
if (template) {
5757
const { render, staticRenderFns } = compileToFunctions(template, {
58-
warn,
58+
warn: msg => warn(msg, this),
5959
shouldDecodeNewlines,
6060
delimiters: options.delimiters
6161
}, this)

test/unit/features/component/component-async.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ describe('Component async', () => {
110110

111111
it('with v-for', done => {
112112
const vm = new Vue({
113-
template: '<div><test v-for="n in list" :n="n"></test></div>',
113+
template: '<div><test v-for="n in list" :key="n" :n="n"></test></div>',
114114
data: {
115115
list: [1, 2, 3]
116116
},

test/unit/features/component/component-slot.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ describe('Component slot', () => {
243243

244244
it('combined with v-for', () => {
245245
const vm = new Vue({
246-
template: '<div><test v-for="i in 3">{{ i }}</test></div>',
246+
template: '<div><test v-for="i in 3" :key="i">{{ i }}</test></div>',
247247
components: {
248248
test: {
249249
template: '<div><slot></slot></div>'

test/unit/features/component/component.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ describe('Component', () => {
166166
const vm = new Vue({
167167
template:
168168
'<div>' +
169-
'<component v-for="c in comps" :is="c.type"></component>' +
169+
'<component v-for="c in comps" :key="c.type" :is="c.type"></component>' +
170170
'</div>',
171171
data: {
172172
comps: [{ type: 'one' }, { type: 'two' }]

test/unit/features/directives/for.spec.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ describe('Directive v-for', () => {
348348
},
349349
template:
350350
'<div>' +
351-
'<test v-for="item in list" :msg="item.a">' +
351+
'<test v-for="item in list" :msg="item.a" :key="item.a">' +
352352
'<span>{{item.a}}</span>' +
353353
'</test>' +
354354
'</div>',
@@ -387,7 +387,7 @@ describe('Directive v-for', () => {
387387
},
388388
template:
389389
'<div>' +
390-
'<component v-for="item in list" :is="item.type"></component>' +
390+
'<component v-for="item in list" :key="item.type" :is="item.type"></component>' +
391391
'</div>',
392392
components: {
393393
one: {
@@ -405,6 +405,19 @@ describe('Directive v-for', () => {
405405
}).then(done)
406406
})
407407

408+
it('should warn component v-for without keys', () => {
409+
new Vue({
410+
template: `<div><test v-for="i in 3"></test></div>`,
411+
components: {
412+
test: {
413+
render () {}
414+
}
415+
}
416+
}).$mount()
417+
expect('<test v-for="i in 3">: component lists rendered with v-for should have explicit keys')
418+
.toHaveBeenWarned()
419+
})
420+
408421
it('multi nested array reactivity', done => {
409422
const vm = new Vue({
410423
data: {

test/unit/features/ref.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe('ref', () => {
121121
},
122122
template: `
123123
<div>
124-
<test v-for="n in items" ref="list" :n="n"></test>
124+
<test v-for="n in items" ref="list" :key="n" :n="n"></test>
125125
</div>
126126
`,
127127
components: {

0 commit comments

Comments
 (0)