Berechnete Eigenschaften
Grundlegendes Beispiel
Vorlageninterne Ausdrücke sind sehr praktisch, aber sie sind für einfache Operationen gedacht. Wenn Sie zu viel Logik in Ihre Vorlagen einbauen, können diese aufgebläht und schwer zu pflegen werden. Zum Beispiel, wenn wir ein Objekt mit einem verschachtelten Array haben:
js
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
Und wir wollen unterschiedliche Meldungen anzeigen, je nachdem, ob Autor
bereits einige Bücher hat oder nicht:
template
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
An diesem Punkt wird die Vorlage ein wenig unübersichtlich. Wir müssen sie eine Sekunde lang betrachten, um zu erkennen, dass sie eine Berechnung in Abhängigkeit von author.books
durchführt. Noch wichtiger ist, dass wir uns wahrscheinlich nicht wiederholen wollen, wenn wir diese Berechnung mehr als einmal in die Vorlage aufnehmen müssen.
Aus diesem Grund wird für komplexe Logik, die reaktive Daten enthält, die Verwendung einer berechneten Eigenschaft empfohlen. Hier ist das gleiche Beispiel, umstrukturiert:
vue
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// a computed ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
Versuchen Sie es auf dem Spielplatz
Hier haben wir eine berechnete Eigenschaft publishedBooksMessage
deklariert. Die Funktion "berechnet()" erwartet die Übergabe einer Getter-Funktion, und der zurückgegebene Wert ist eine berechnete Referenz. Ähnlich wie bei normalen Refs kann man auf das berechnete Ergebnis als publishedBooksMessage.value
zugreifen. Berechnete Refs werden auch automatisch in Templates entpackt, so dass man sie ohne .value
in Template-Ausdrücken referenzieren kann.
Eine berechnete Eigenschaft verfolgt automatisch ihre reaktiven Abhängigkeiten. Vue ist sich bewusst, dass die Berechnung von publishedBooksMessage
von author.books
abhängt, also wird es alle Bindungen, die von publishedBooksMessage
abhängen, aktualisieren, wenn sich author.books
ändert.
Siehe auch: Typing Computed
Berechnetes Caching vs. Methoden
Sie haben vielleicht bemerkt, dass wir das gleiche Ergebnis durch den Aufruf einer Methode im Ausdruck erreichen können:
template
<p>{{ calculateBooksMessage() }}</p>
js
// in component
function calculateBooksMessage() {
return author.books.length > 0 ? 'Yes' : 'No'
}
Anstelle einer berechneten Eigenschaft können wir die gleiche Funktion als Methode definieren. Was das Endergebnis betrifft, sind die beiden Ansätze tatsächlich genau gleich. Der Unterschied besteht jedoch darin, dass berechnete Eigenschaften auf der Grundlage ihrer reaktiven Abhängigkeiten zwischengespeichert werden. Eine berechnete Eigenschaft wird nur dann neu ausgewertet, wenn sich einige ihrer reaktiven Abhängigkeiten geändert haben. Das heißt, solange sich author.books
nicht geändert hat, wird ein mehrfacher Zugriff auf publishedBooksMessage
sofort das zuvor berechnete Ergebnis zurückgeben, ohne dass die Getter-Funktion erneut ausgeführt werden muss.
Das bedeutet auch, dass die folgende berechnete Eigenschaft nie aktualisiert wird, da "date.now()" keine reaktive Abhängigkeit ist:
js
const now = computed(() => Date.now())
Im Vergleich dazu wird bei einem Methodenaufruf die Funktion immer ausgeführt, wenn eine Neuberechnung erfolgt.
Warum brauchen wir eine Zwischenspeicherung? Stellen Sie sich vor, wir haben eine teure berechnete Eigenschaft list
, die eine Schleife durch ein großes Array und viele Berechnungen erfordert. Dann haben wir vielleicht andere berechnete Eigenschaften, die wiederum von list
abhängen. Ohne Zwischenspeicherung würden wir den Getter von list
viel öfter als nötig ausführen! In Fällen, in denen Sie keine Zwischenspeicherung wünschen, verwenden Sie stattdessen einen Methodenaufruf.
Beschreibbar Berechnet
Berechnete Eigenschaften sind standardmäßig nur Getter-Eigenschaften. Wenn Sie versuchen, einer berechneten Eigenschaft einen neuen Wert zuzuweisen, erhalten Sie eine Laufzeitwarnung. In den seltenen Fällen, in denen Sie eine "beschreibbare" berechnete Eigenschaft benötigen, können Sie eine erstellen, indem Sie sowohl einen Getter als auch einen Setter bereitstellen:
vue
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
Wenn Sie nun fullName.value = 'John Doe'
ausführen, wird der Setter aufgerufen und firstName
und lastName
werden entsprechend aktualisiert.
Beste Praktiken
Getter sollten nebenwirkungsfrei sein
Es ist wichtig, daran zu denken, dass berechnete Getter-Funktionen nur reine Berechnungen durchführen und frei von Nebeneffekten sein sollten. Stellen Sie sich eine berechnete Eigenschaft als eine deklarative Beschreibung vor, die beschreibt, wie ein Wert auf der Grundlage anderer Werte abgeleitet wird - ihre einzige Aufgabe sollte die Berechnung und Rückgabe dieses Wertes sein. Später im Handbuch werden wir besprechen, wie wir Seiteneffekte in Reaktion auf Zustandsänderungen mit watchers.
Mutation des berechneten Wertes vermeiden
Der von einer berechneten Eigenschaft zurückgegebene Wert ist ein abgeleiteter Zustand. Betrachten Sie ihn als einen temporären Schnappschuss - jedes Mal, wenn sich der Quellzustand ändert, wird ein neuer Schnappschuss erstellt. Es ist nicht sinnvoll, einen Schnappschuss zu verändern, daher sollte ein berechneter Rückgabewert als schreibgeschützt behandelt und niemals verändert werden - aktualisieren Sie stattdessen den Quellzustand, von dem er abhängt, um neue Berechnungen auszulösen.