Konsolenwarnung: Mit v-for gerenderte Komponentenlisten sollten explizite Schlüssel haben

75

Ich habe hier ein Problem, ich weiß nicht, was in meinem Code falsch ist, aber ich habe eine Warnung in meiner Konsole. Wie kann ich diese Warnung entfernen?

[Vue-Tipp] <todo-item v-for="todoItem in todos">:: Mit v-for gerenderte Komponentenlisten sollten explizite Schlüssel haben. Weitere Informationen finden Sie unter https://vuejs.org/v2/guide/list.html#key .
(gefunden in <Root>)

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vue Tutorial</title>
        <link rel="shortcut icon" href="https://vuejs.org/images/logo.png">
        <script src="scripts/vue.js"></script>
    </head>
    <body>
        <section id="app">
            <p>{{ msg }}</p>
            <p v-bind:title="message">
                Hover your mouse over me for a few seconds to see my dynamically bound title!
            </p>
            <div>
                <p v-if="seen">This text will show or hide if the button was clicked.</p>
                <button type="button" v-on:click="isSeen">{{ isSeenText }}</button>
            </div>
            <ol>
                <li v-for="todo in todos">
                    {{ todo.text }}
                </li>
            </ol>
            <p>Total count: {{ todos.length }}</p>
            <div v-bind:title="reverseMessageText">
                <p>{{ reverseMessageText }}</p>
                <button v-on:click="reverseMessage">Reverse Message</button>
            </div>
            <div>
                <p>Data binding: <strong>{{ nameOfUser }}</strong></p>
                <input type="text" v-model="nameOfUser">
            </div>
            <div>
                <ol>
                    <todo-item v-for="todoItem in todos" v-bind:data="todoItem"></todo-item>
                </ol>
            </div>
        </section>
        <script src="scripts/app.js"></script>
    </body>
</html>

app.js.

var appComponent = Vue.component('todo-item', {
    template: '<li>id: {{ data.id }}<br>text: {{ data.text }}</li>',
    props: [
        'data'
    ]
});

new Vue({
    el: '#app',
    data: {
        msg: 'Hello World!',
        message: 'You loaded this page on ' + new Date(),
        seen: true,
        isSeenText: 'Now you don\'t',
        todos: [
            {
                text: 'Learn JavaScript'
            },
            {
                text: 'Learn Vue'
            },
            {
                text: 'Build something awesome'
            }
        ],
        reverseMessageText: 'Hello World from Vue.js!',
        nameOfUser: 'John Rey'
    },
    methods: {
        reverseMessage: function() {
            this.reverseMessageText = this.reverseMessageText.split('').reverse().join('');
        },
        isSeen: function() {
            this.seen = !this.seen;
            this.isSeenText = this.seen ? 'Now you don\'t' : 'Now you see me';
        }
    }
});


console.log

Geben Sie hier die Bildbeschreibung ein

Hier ist der Link, den Vue hier vorgeschlagen hat . Ich glaube, ich habe keinen Fehler, ich möchte diese Warnung lösen, aber ich kann nicht herausfinden, wo die Ursache liegt, übrigens bin ich Neuling hier bei Vue.

John Rey M. Baylen
quelle

Antworten:

107

Die Antwort ist in der von Ihnen verlinkten Dokumentation explizit aufgeführt ...

<todo-item v-for="todoItem in todos"
           v-bind:data="todoItem"
           v-bind:key="todoItem.text"></todo-item>

Um einige Informationen aus den Kommentaren unten zusammenzufassen ... verwenden Sie diese Option :key, um die Komponente über die Identifizierung einzelner Elemente zu informieren. Dies ermöglicht es, Änderungen für die Reaktivität von Vue zu verfolgen .

Versuchen Sie am besten, :keydie Eigenschaft an eine eindeutig identifizierende Eigenschaft jedes Elements zu binden . Zum Beispiel ein id.

Phil
quelle
1
In meinem Fall möchte ich, dass das gesamte ToDo-Objekt an <todo-item> übergeben wird. Ich möchte nicht nur den .text übergeben. Ist das möglich?
Kokodoko
@kokodoko Der gesamte Artikel wird über die Unterkunft übergeben data. Sie verwenden key, um die Komponente wissen zu lassen, wie einzelne Elemente zu identifizieren sind
Phil
1
ok, danke, der Schlüssel ist nur eine Möglichkeit für vue, den Überblick zu behalten. Sie müssen also einen Wert haben, der als Schlüssel verwendet werden kann.
Kokodoko
1
@ Kokodoko ja, das ist es genau
Phil
7

Meine Lösung für ein ähnliches Problem sah folgendermaßen aus:

- <el-radio v-for="option in field.options"> ...
+ <el-radio v-for="(option, index) in field.options" :key="index"> ...

Oder verwenden Sie die v-bindSyntax für index:

+ <el-radio v-for="(option, index) in field.options" v-bind:key="index"> ...
Henry
quelle
Dies ist eine großartige Lösung. Meine Elemente sind nicht wirklich einzigartig. Das löst es also.
Khan
1

Sie können jedes Feld Ihrer Daten als Schlüssel verwenden. Außerdem können Sie die Standard-ID verwenden. Darüber hinaus können Sie in Ihren Daten einen "Schlüssel" wie im folgenden Code definieren:

Vue.component('task-list', {
template:  `
<div><slot>
    <task v-for="task in tasks" :key="task.key">  {{task.description}}</task>
</slot></div>
`,
data () {
    return {
        tasks: [
                {description:"Go to market", completed:false, key:"asd"},
                {description:"Wake up ", completed:true, key:"rty"},
                {description:"Sleep", completed:false, key:"terw"},
                {description:"Have breakfast", completed:true, key:"jdr"},
        ]
    };
},
});
Vue.component('task', {
   template: `<li><slot></slot></li>`
});

An die Stelle des Schlüssels in der task.key können Sie einen der Feldnamen einschließlich der versteckten ID setzen.

Ioannis Chrysochos
quelle