Skip to content

Liste Rendering

v-for

Wir können die v-for Direktive verwenden, um eine Liste von Elementen auf der Grundlage eines Arrays darzustellen. Die v-for Direktive erfordert eine spezielle Syntax in der Form item in items, wobei items as Quelldaten-Array ist und item ein alias für das Array-Element ist, über das iteriert wird:

js
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
js
data() {
  return {
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
template
<li v-for="item in items">
  {{ item.message }}
</li>

Innerhalb des Bereichs v-for haben die Schablonenausdrücke Zugriff auf alle Eigenschaften des übergeordneten Bereichs. Darüber hinaus unterstützt v-for auch einen optionalen zweiten Alias für den Index des aktuellen Elements:

js
const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
js
data() {
  return {
    parentMessage: 'Parent',
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
template
<li v-for="(item, index) in items">
  {{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
  • Parent - 0 - Foo
  • Parent - 1 - Bar
  • Die Variablenzuordnung von v-for ähnelt dem folgenden JavaScript:

    js
    const parentMessage = 'Parent'
    const items = [
      /* ... */
    ]
    
    items.forEach((item, index) => {
      // has access to outer scope `parentMessage`
      // but `item` and `index` are only available in here
      console.log(parentMessage, item.message, index)
    })

    Beachten Sie, dass der v-for Wert mit der Funktionssignatur des forEach Callbacks übereinstimmt. In der Tat können Sie die Destrukturierung auf den v-for Element-Alias anwenden, ähnlich wie bei der Destrukturierung von Funktionsargumenten:

    template
    <li v-for="{ message } in items">
      {{ message }}
    </li>
    
    <!-- with index alias -->
    <li v-for="({ message }, index) in items">
      {{ message }} {{ index }}
    </li>

    Bei verschachtelten v-for, Bereichen funktioniert das Scoping ähnlich wie bei verschachtelten Funktionen. Jeder v-for Bereich hat Zugriff auf übergeordnete Bereiche:

    template
    <li v-for="item in items">
      <span v-for="childItem in item.children">
        {{ item.message }} {{ childItem }}
      </span>
    </li>

    Sie können auch of als Begrenzungszeichen anstelle von in verwenden, so dass es näher an der JavaScript-Syntax für Iteratoren ist:

    template
    <div v-for="item of items"></div>

    v-for mit einem Objekt

    Sie können auch v-for verwenden, um durch die Eigenschaften eines Objekts zu iterieren. Die Iterationsreihenfolge basiert auf dem Ergebnis des Aufrufs von Object.keys() für das Objekt:

    js
    const myObject = reactive({
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    })
    js
    data() {
      return {
        myObject: {
          title: 'How to do lists in Vue',
          author: 'Jane Doe',
          publishedAt: '2016-04-10'
        }
      }
    }
    template
    <ul>
      <li v-for="value in myObject">
        {{ value }}
      </li>
    </ul>

    Sie können auch einen zweiten Alias für den Namen der Eigenschaft (auch bekannt als Schlüssel) angeben:

    template
    <li v-for="(value, key) in myObject">
      {{ key }}: {{ value }}
    </li>

    Und eine weitere für den Index:

    template
    <li v-for="(value, key, index) in myObject">
      {{ index }}. {{ key }}: {{ value }}
    </li>

    v-for mit einem Bereich

    v-for kann auch eine ganze Zahl annehmen. In diesem Fall wird die Vorlage so oft wiederholt, basierend auf einem Bereich von 1...n.

    template
    <span v-for="n in 10">{{ n }}</span>

    Man beachte, dass n mit einem Anfangswert von 1 anstelle von of 0 beginnt.

    v-for on <template>

    Ähnlich wie bei der Vorlage v-if können Sie auch ein <template> Tag mit v-for verwenden, um einen Block mit mehreren Elementen darzustellen. Zum Beispiel:

    template
    <ul>
      <template v-for="item in items">
        <li>{{ item.msg }}</li>
        <li class="divider" role="presentation"></li>
      </template>
    </ul>

    v-for mit v-if

    :::Warnung Hinweis Es wird nicht empfohlen, v-if und v-for für dasselbe Element zu verwenden, da sie implizit Vorrang haben. Siehe style guide für Details. :::

    Wenn sie auf demselben Knoten existieren, hat v-if eine höhere Priorität als v-for. Das bedeutet, dass die v-if Bedingung keinen Zugriff auf Variablen aus dem Bereich von v-for hat:

    template
    <!--
    Dies führt zu einem Fehler, da die Eigenschaft "todo"
    in der Instanz nicht definiert ist.
    -->
    <li v-for="todo in todos" v-if="!todo.isComplete">
      {{ todo.name }}
    </li>

    Dies kann behoben werden, indem v-for in ein umhüllendes <template>-Tag verschoben wird (was auch eindeutiger ist):

    template
    <template v-for="todo in todos">
      <li v-if="!todo.isComplete">
        {{ todo.name }}
      </li>
    </template>

    Aufrechterhaltung des Zustands mit key

    Wenn Vue eine Liste von Elementen aktualisiert, die mit v-for gerendert werden, verwendet es standardmäßig eine "in-place patch" Strategie. Wenn sich die Reihenfolge der Datenelemente geändert hat, wird Vue, anstatt die DOM-Elemente zu verschieben, um die Reihenfolge der Elemente anzupassen, jedes Element an Ort und Stelle patchen und sicherstellen, dass es widerspiegelt, was an diesem bestimmten Index gerendert werden sollte.

    Dieser Standardmodus ist effizient, aber nur geeignet, wenn die Ausgabe der Liste nicht auf dem Zustand der untergeordneten Komponenten oder dem temporären DOM-Zustand (z. B. Formulareingabewerte) beruht.

    Um Vue einen Hinweis zu geben, so dass es die Identität jedes Knotens verfolgen und somit bestehende Elemente wiederverwenden und neu anordnen kann, müssen Sie ein eindeutiges key-Attribut für jedes Element angeben:

    template
    <div v-for="item in items" :key="item.id">
      <!-- content -->
    </div>

    Bei der Verwendung von <template v-for>, sollte der key auf dem <template> Container platziert werden::

    template
    <template v-for="todo in todos" :key="todo.name">
      <li>{{ todo.name }}</li>
    </template>

    :::Tipp Hinweis key ist hier ein spezielles Attribut, das mit v-bind gebunden wird. Es sollte nicht mit der Eigenschaftsvariable "key" verwechselt werden, wenn v-for mit einem Objekt. :::

    Es wird empfohlen ein key Attribut mit v-for bereitzustellen, wann immer dies möglich ist, es sei denn, der iterierte DOM-Inhalt ist einfach (d.h. er enthält keine Komponenten oder zustandsbehafteten DOM-Elemente), oder Sie verlassen sich absichtlich auf das Standardverhalten, um die Leistung zu steigern.

    Die key Bindung erwartet primitive Werte - d.h. Strings und Zahlen. Verwenden Sie keine Objekte als v-for Schlüssel. Für die detaillierte Verwendung des key Attributs, lesen Sie bitte die key API Dokumentation.

    v-for mit einer Komponente

    Dieser Abschnitt setzt Kenntnisse über [Komponenten].(/guide/essentials/component-basics) voraus. Sie können es auch überspringen und später wiederkommen.

    Sie können v-for direkt auf eine Komponente anwenden, wie jedes normale Element (vergessen Sie nicht, einen key anzugeben):

    template
    <MyComponent v-for="item in items" :key="item.id" />

    Dadurch werden jedoch nicht automatisch Daten an die Komponente übergeben, da Komponenten über eigene isolierte Bereiche verfügen. Um die iterierten Daten an die Komponente zu übergeben, sollten wir auch props verwenden:

    template
    <MyComponent
      v-for="(item, index) in items"
      :item="item"
      :index="index"
      :key="item.id"
    />

    Der Grund dafür, dass item nicht automatisch in die Komponente injiziert wird, ist, dass die Komponente dadurch eng an die Funktionsweise von v-for gekoppelt ist. Wenn explizit angegeben wird, woher die Daten kommen, kann die Komponente in anderen Situationen wiederverwendet werden.

    Siehe dieses Beispiel für eine einfache ToDo-Liste um zu sehen, wie eine Liste von Komponenten mit v-for gerendert werden kann, wobei jeder Instanz unterschiedliche Daten übergeben werden.

    Siehe dieses Beispiel für eine einfache ToDo-Liste um zu sehen, wie eine Liste von Komponenten mit v-for gerendert werden kann, wobei jeder Instanz unterschiedliche Daten übergeben werden.

    Erkennung von Array-Änderungen

    Mutationsmethoden

    Vue ist in der Lage zu erkennen, wann die Mutationsmethoden eines reaktiven Arrays aufgerufen werden und löst die notwendigen Aktualisierungen aus. Diese Mutationsmethoden sind:

    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()

    Ersetzen eines Arrays

    Mutationsmethoden verändern, wie der Name schon sagt, das ursprüngliche Array, auf dem sie aufgerufen werden. Im Vergleich dazu gibt es auch nicht-mutierende Methoden, z.B. filter(), concat() und slice(), die das ursprüngliche Array nicht verändern, sondern immer ein neues Array zurückgeben. Wenn man mit nicht-mutierenden Methoden arbeitet, sollte man das alte Array durch das neue ersetzen:

    js
    // `items` is a ref with array value
    items.value = items.value.filter((item) => item.message.match(/Foo/))
    js
    this.items = this.items.filter((item) => item.message.match(/Foo/))

    Man könnte meinen, dass dies dazu führt, dass Vue das bestehende DOM wegwirft und die gesamte Liste neu gerendert wird - zum Glück ist das nicht der Fall. Vue implementiert einige intelligente Heuristiken, um die Wiederverwendung von DOM-Elementen zu maximieren, so dass das Ersetzen eines Arrays durch ein anderes Array mit überlappenden Objekten eine sehr effiziente Operation ist.

    Gefilterte/sortierte Ergebnisse anzeigen

    Manchmal möchte man eine gefilterte oder sortierte Version eines Arrays anzeigen, ohne die Originaldaten zu verändern oder zurückzusetzen. In diesem Fall können Sie eine berechnete Eigenschaft erstellen, die das gefilterte oder sortierte Array zurückgibt.

    Zum Beispiel:

    js
    const numbers = ref([1, 2, 3, 4, 5])
    
    const evenNumbers = computed(() => {
      return numbers.value.filter((n) => n % 2 === 0)
    })
    js
    data() {
      return {
        numbers: [1, 2, 3, 4, 5]
      }
    },
    computed: {
      evenNumbers() {
        return this.numbers.filter(n => n % 2 === 0)
      }
    }
    template
    <li v-for="n in evenNumbers">{{ n }}</li>

    In Situationen, in denen berechnete Eigenschaften nicht durchführbar sind (z. B. innerhalb von verschachtelten v-for Schleifen), können Sie eine Methode verwenden:

    js
    const sets = ref([
      [1, 2, 3, 4, 5],
      [6, 7, 8, 9, 10]
    ])
    
    function even(numbers) {
      return numbers.filter((number) => number % 2 === 0)
    }
    js
    data() {
      return {
        sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
      }
    },
    methods: {
      even(numbers) {
        return numbers.filter(number => number % 2 === 0)
      }
    }
    template
    <ul v-for="numbers in sets">
      <li v-for="n in even(numbers)">{{ n }}</li>
    </ul>

    Seien Sie vorsichtig mit reverse() und sort() in einer berechneten Eigenschaft! Diese beiden Methoden verändern das ursprüngliche Array, was in berechneten Gettern vermieden werden sollte. Erstellen Sie eine Kopie des ursprünglichen Arrays, bevor Sie diese Methoden aufrufen:

    diff
    - return numbers.reverse()
    + return [...numbers].reverse()
    Liste Rendering has loaded