Procházet zdrojové kódy

warn v-for component lists without explicit keys

Evan You před 9 roky
rodič
revize
5ae63d9d2f

+ 12 - 0
src/compiler/codegen/index.js

@@ -144,6 +144,18 @@ function genFor (el: any): string {
   const alias = el.alias
   const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
   const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
+
+  if (
+    process.env.NODE_ENV !== 'production' &&
+    maybeComponent(el) && el.tag !== 'slot' && el.tag !== 'template' && !el.key
+  ) {
+    warn(
+      `<${el.tag} v-for="${alias} in ${exp}">: component lists rendered with ` +
+      `v-for should have explicit keys. ` +
+      `See https://vuejs.org/guide/list.html#key for more info.`
+    )
+  }
+
   el.forProcessed = true // avoid recursion
   return `_l((${exp}),` +
     `function(${alias}${iterator1}${iterator2}){` +

+ 1 - 1
src/compiler/helpers.js

@@ -3,7 +3,7 @@
 import { parseFilters } from './parser/filter-parser'
 
 export function baseWarn (msg: string) {
-  console.error(`[Vue parser]: ${msg}`)
+  console.error(`[Vue compiler]: ${msg}`)
 }
 
 export function pluckModuleFunction<F: Function> (

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

@@ -55,7 +55,7 @@ Vue.prototype.$mount = function (
     }
     if (template) {
       const { render, staticRenderFns } = compileToFunctions(template, {
-        warn,
+        warn: msg => warn(msg, this),
         shouldDecodeNewlines,
         delimiters: options.delimiters
       }, this)

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

@@ -110,7 +110,7 @@ describe('Component async', () => {
 
   it('with v-for', done => {
     const vm = new Vue({
-      template: '<div><test v-for="n in list" :n="n"></test></div>',
+      template: '<div><test v-for="n in list" :key="n" :n="n"></test></div>',
       data: {
         list: [1, 2, 3]
       },

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

@@ -243,7 +243,7 @@ describe('Component slot', () => {
 
   it('combined with v-for', () => {
     const vm = new Vue({
-      template: '<div><test v-for="i in 3">{{ i }}</test></div>',
+      template: '<div><test v-for="i in 3" :key="i">{{ i }}</test></div>',
       components: {
         test: {
           template: '<div><slot></slot></div>'

+ 1 - 1
test/unit/features/component/component.spec.js

@@ -166,7 +166,7 @@ describe('Component', () => {
     const vm = new Vue({
       template:
         '<div>' +
-          '<component v-for="c in comps" :is="c.type"></component>' +
+          '<component v-for="c in comps" :key="c.type" :is="c.type"></component>' +
         '</div>',
       data: {
         comps: [{ type: 'one' }, { type: 'two' }]

+ 15 - 2
test/unit/features/directives/for.spec.js

@@ -348,7 +348,7 @@ describe('Directive v-for', () => {
       },
       template:
         '<div>' +
-          '<test v-for="item in list" :msg="item.a">' +
+          '<test v-for="item in list" :msg="item.a" :key="item.a">' +
             '<span>{{item.a}}</span>' +
           '</test>' +
         '</div>',
@@ -387,7 +387,7 @@ describe('Directive v-for', () => {
       },
       template:
         '<div>' +
-          '<component v-for="item in list" :is="item.type"></component>' +
+          '<component v-for="item in list" :key="item.type" :is="item.type"></component>' +
         '</div>',
       components: {
         one: {
@@ -405,6 +405,19 @@ describe('Directive v-for', () => {
     }).then(done)
   })
 
+  it('should warn component v-for without keys', () => {
+    new Vue({
+      template: `<div><test v-for="i in 3"></test></div>`,
+      components: {
+        test: {
+          render () {}
+        }
+      }
+    }).$mount()
+    expect('<test v-for="i in 3">: component lists rendered with v-for should have explicit keys')
+      .toHaveBeenWarned()
+  })
+
   it('multi nested array reactivity', done => {
     const vm = new Vue({
       data: {

+ 1 - 1
test/unit/features/ref.spec.js

@@ -121,7 +121,7 @@ describe('ref', () => {
       },
       template: `
         <div>
-          <test v-for="n in items" ref="list" :n="n"></test>
+          <test v-for="n in items" ref="list" :key="n" :n="n"></test>
         </div>
       `,
       components: {