Das Javascript-Framework Vue.js, Teil 6 Datenüberwachung mit Computed Properties und Watchern

Von Dr. Dirk Koller

Anbieter zum Thema

Wer Daten innerhalb ihrer Vue-Komponenten automatisiert ändern oder andere Aktionen auslösen möchte, kann hierfür Computed Properties und Watcher nutzen. Hier zeigen wir, wie sich diese beiden Funktionen nutzen lassen.

Vue stellt zwei mächtige Werkzeuge zur Verfügung, um Änderungen an Daten zu registrieren und darauf zu reagieren.
Vue stellt zwei mächtige Werkzeuge zur Verfügung, um Änderungen an Daten zu registrieren und darauf zu reagieren.
(© Nmedia - stock.adobe.com)

In der Softwareentwicklung ist es üblich, Daten möglichst normalisiert und nicht mehrfach abzuspeichern. Zur Verwahrung der Daten eines Kunden sieht man deshalb Attribute wie Anrede, Vor- und Nachname, aber kein weiteres Feld für den zusammengesetzten Namen vor. Der komplette Name in der Form Herr Max Mustermann lässt sich schließlich jederzeit aus den Bestandteilen zusammensetzen.

Um das aber nicht an mehreren Stellen und zudem auf stets konsistente Art und Weise machen zu müssen, lassen sich in Vue sogenannte „Computed Properties“ einsetzen. Im Options-Objekt werden sie hinter dem Schlüssel computed aufgeführt. Das folgende Codestück zeigt ein Beispiel für eine solche berechnete Eigenschaft namens displayName, das die geschilderte Problematik umsetzt:

<template>
  <div id="app">
    {{ displayName }}
    <button @click="firstname='Moritz'">Ändere Vornamen</button>
  </div>
</template>
<script>export default {
  data: function () {
    return {
      salutation: 'Herr',
      firstname: 'Max',
      lastname: 'Mustermann'
    }
  },
  computed: {
    displayName: function () {
      return this.salutation + ' ' + this.firstname + ' ' + this.lastname;
    }
  }
}
</script>

Wie im Template zu sehen ist, lässt sich die Computed Property wie eine normale Eigenschaft beispielsweise in einer String Interpolation verwenden. Auf dynamische Änderungen der in der Computed-Funktion verwendeten Bestandteile, wie sie hier bei Klick auf den Button durchgeführt werden, reagiert sie selbstverständlich.

Jede Änderung an einem der zur Berechnung genutzten Bestandteile führt also zur Neuberechnung der Computed Property. Bleiben die zugrundeliegenden Werte unverändert, wird beim Zugriff ein gecachter Wert zurückgegeben, die Funktion zur Berechnung wird dann nicht durchlaufen.

Im oben dargestellten einfachsten Fall wird die hinterlegte Funktion nur beim lesenden (get-) Zugriff auf die Property ausgeführt. Es lassen sich aber auch Funktionen hinterlegen, die beim Setzen des Werts einer Computed Property aufgerufen werden. Das folgende Codestück demonstriert das für displayName:

computed: {
  displayName: {
    get: function () {
      return this.salutation + ' ' + this.firstname + ' ' + this.lastname;
    },
    set: function (newValue) {
      var names = newValue.split(' ')
      this.salutation = names[0]
      this.firstName = names[1]
      this.lastName = names[2]
    }
  }
}

Die Liste der Anwendungsfälle für Computed Properties lässt sich beliebig verlängern, als einfache Beispiele seien hier noch der Umfang eines Kreises (mit dem Radius als gespeicherte Eigenschaft) oder eine alternative Temperaturausgabe in Fahrenheit (mit dem Celsius-Wert als Eigenschaft) genannt.

Überwachen von Daten: Watcher

Eng verwandt mit den Computed Properties sind die Watcher. Auch mit ihnen lassen sich komplexe Ausdrücke oder Aktionen basierend auf geänderten Bestandteilen „berechnen“. Sie werden immer dann verwendet, wenn die Operationen asynchron durchgeführt werden müssen, zeitlich aufwendiger sind oder das Ergebnis nicht die Änderung eines einzelnen State ist, sondern es eher um Seiteneffekte geht.

Hinter dem Schlüssel watch werden dabei die zu observierenden Daten aufgeführt. Tritt eine Änderung in diesen Daten auf, wird der Code in der Funktion ausgeführt. Im folgenden Beispiel wird ein Kundenstatus überwacht, der in einer Auswahlliste ausgewählt wird. Abhängig vom ausgewählten Status (Neukunde, Bestandskunde, Mitarbeiter) wird dann ein anderer Preis berechnet:

<template>
  <div id="app">
    {{ price }}
    <select v-model="kundenstatus">
      <option disabled value="">Kundenstatus auswählen:</option>
      <option>Neukunde</option>
      <option>Bestandkunde</option>
      <option>Mitarbeiter</option>
    </select>
  </div>
</template>
<script>
export default {
  data: function () {
    return {
      kundenstatus: "Neukunde",
      price: 100,
    };
  },
  watch: {
    kundenstatus: function () {
      if (this.kundenstatus === "Neukunde") {
        this.price = 100;
      } else if (this.kundenstatus === "Bestandkunde") {
      this.price = 75;
      } else {
        this.price = 50;
      }
    },
  },
};
</script>

Alternativ lässt sich bei Auftreten einer Datenänderung auch einfach eine separate Methode mit Namen verwenden. Das hat den Vorteil, dass sie wiederverwendet und auch von anderer Stelle aus aufgerufen werden kann:

watch: {
  kundenstatus: "calculatePrice"
},
methods: {
  calculatePrice() {
    if (this.kundenstatus === "Neukunde") {
      this.price = 100;
    } else if (this.kundenstatus === "Bestandkunde") {
      this.price =
75;
    } else {
      this.price = 50;
    }
  }
}

In der data-Funktion oben wird der Preis initial auf 100 gesetzt, damit er zu dem Default-Wert Neukunde passt. Das ist nicht so schön, bei Preisänderungen müsste die 100 sowohl in der data-Funktion als auch in der Methode calculatePrice abgeändert werden. Eleganter ist es, mit Hilfe der Eigenschaft immediate die Methode direkt nach dem Start der Beobachtung initial ausführen zu lassen. Der watch-Code für kundenstatus wird dazu als Objekt formuliert und der Name der Methode hinter dem Schlüssel handler aufgeführt:

watch: {
  kundenstatus: {
    handler: "calculatePrice",
    immediate: true
  }
},

Eine weitere wichtige Eigenschaft für Watcher ist deep. Damit lassen sich verschachtelte Daten überwachen. Wenn beispielsweise einem überwachten Array ein Element zugefügt wird, dann zeigt die Variable weiterhin auf das gleiche Objekt. Die Änderung wird mit nur bei Verwendung von deep registriert:

watch: {
  person: {
    deep: true,
    handler: "personChanged"
  }
}

Vue stellt mit Computed Properties und Watchern zwei mächtige Werkzeuge zur Verfügung, um Änderungen an Daten zu registrieren und darauf zu reagieren. Die Wahl des Werkzeugs ist aber nicht immer ganz leicht. Computed Properties sind zu bevorzugen wenn eine Property, deren Wert auf anderen Properties basiert, neu berechnet werden soll. Hier werden also die zugrundeliegenden Bestandteile überwacht. Watchers dagegen kommen eher bei Aktionen zum Einsatz, die als Folge der Änderung einer Property ausgeführt werden sollen. Weitere Informationen finden sich im Vue-Guide.

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Softwareentwicklung und DevOps

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung

(ID:48079876)