Methoden, Computed und Watcher in Vue.js

Avatar of Sarah Drasner
Sarah Drasner am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Einer der Gründe, warum ich gerne mit Vue arbeite, ist die Nützlichkeit von methods, computed und watchers sowie die Klarheit ihrer Unterscheidung. Bis man alle drei verstanden hat, ist es schwierig, die Funktionalität von Vue voll auszuschöpfen. Dennoch sind die meisten Leute, die ich mit diesem Framework verwirrt sehe, auch über die Unterschiede hier verwirrt, also tauchen wir ein.

Falls Sie eine schnelle Antwort benötigen und keine Zeit haben, den gesamten Artikel zu lesen, hier ist ein kleines TL;DR

  • Methoden: Dies sind genau das, wonach sie klingen könnten (yay, Namensgebung!). Es sind Funktionen, die an ein Objekt angehängt sind – typischerweise die Vue-Instanz selbst oder eine Vue-Komponente.
  • Computed: Diese Eigenschaften könnten zunächst so aussehen, als ob sie wie eine Methode verwendet würden, sind es aber nicht. In Vue verwenden wir data, um Änderungen an einer bestimmten Eigenschaft zu verfolgen, die reaktiv sein soll. Computed Properties ermöglichen es uns, eine Eigenschaft zu definieren, die genauso verwendet wird wie data, aber auch benutzerdefinierte Logik enthalten kann, die basierend auf ihren Abhängigkeiten gecached wird. Sie können Computed Properties als *eine weitere Ansicht Ihrer Daten* betrachten.
  • Watcher: Diese ermöglichen uns einen Einblick in das Reaktivitätssystem. Wir erhalten einige Hooks, mit denen wir alle von Vue gespeicherten Eigenschaften beobachten können. Wenn wir jedes Mal, wenn etwas passiert, ein wenig Funktionalität hinzufügen oder auf eine bestimmte Änderung reagieren möchten, könnten wir eine Eigenschaft beobachten und einige Logiken anwenden. Das bedeutet, dass der Name des Watchers *mit dem übereinstimmen muss*, was wir beobachten wollen.

Wenn Ihnen das alles verwirrend erscheint, machen Sie sich keine Sorgen! Wir werden unten weiter eintauchen und hoffentlich alle Unklarheiten beseitigen. Wenn Sie mit Vanilla JavaScript bereits vertraut sind, sind Methoden wahrscheinlich ziemlich offensichtlich für Sie, abgesehen von ein oder zwei Vorbehalten. Es könnte sich dann für Sie lohnen (ich liebe diesen Ausdruck), zu den Abschnitten Computed und Watchers zu springen.

Methoden

Methoden sind wahrscheinlich etwas, das Sie bei der Arbeit mit Vue viel verwenden werden. Sie sind treffend benannt, da wir im Wesentlichen eine Funktion an ein Objekt anhängen. Sie sind unglaublich nützlich, um Funktionalität mit Direktiven für Ereignisse zu verbinden oder um einfach ein kleines Stück Logik zu erstellen, das wie jede andere Funktion wiederverwendet werden kann. Sie können zum Beispiel eine Methode innerhalb einer anderen Methode aufrufen. Sie können auch eine Methode innerhalb eines Lifecycle Hooks aufrufen. Sie sind sehr vielseitig.

Hier ist eine einfache Demo zur Veranschaulichung

Siehe den Pen Slim example of methods von Sarah Drasner (@sdras) auf CodePen.

<code class="language-css"><div id="app">
  <button @click="tryme">Try Me</button>
  <p>{{ message }}</p>
</div>
new Vue({
  el: '#app',
  data() {
    return {
      message: null
    }
  },
  methods: {
    tryme() {
      this.message = Date()
    }
  }
})

Wir hätten die Logik auch direkt in der Direktive ausführen können, wie <button @click="message = Date()">Try Me</button>, was für dieses kleine Beispiel sehr gut funktioniert. Wenn jedoch die Komplexität unserer Anwendung wächst, ist es üblicher, wie oben gezeigt zu verfahren, um sie aufzuteilen und lesbar zu halten. Es gibt auch eine Grenze für die Logik, die Vue in einer Direktive zulässt – zum Beispiel sind Ausdrücke erlaubt, aber keine Anweisungen.

Sie werden vielleicht bemerken, dass wir innerhalb dieser Komponente oder Vue-Instanz auf diese Methode zugreifen können und hier auf jedes beliebige Stück unserer Daten zugreifen können, in diesem Fall this.message. Sie müssen eine Methode nicht so aufrufen, wie Sie eine Funktion innerhalb einer Direktive aufrufen würden. Zum Beispiel ist @click=”methodName()” unnötig. Sie können sie mit @click=”methodName” referenzieren, es sei denn, Sie müssen einen Parameter übergeben, wie z.B. @click=”methodName(param)”.

Die Verwendung von Direktiven zum Aufrufen von Methoden ist auch gut, da wir einige vorhandene Modifikatoren haben. Ein nützliches Beispiel ist .prevent, das ein Sendeereignis daran hindert, die Seite neu zu laden. Es wird so verwendet:

<form v-on:submit.prevent="onSubmit"></form>

Es gibt noch viele weitere, hier sind nur einige wenige.

Computed

Computed Properties sind sehr wertvoll für die Manipulation vorhandener Daten. Wann immer Sie etwas bauen, bei dem Sie eine große Menge von Daten durchsuchen müssen und diese Berechnungen nicht bei jedem Tastendruck neu ausführen möchten, denken Sie an die Verwendung eines computed-Werts.

Gute Kandidaten sind unter anderem, aber nicht nur:

  • Aktualisieren einer großen Menge von Informationen, während ein Benutzer tippt, z. B. Filtern einer Liste
  • Sammeln von Informationen aus Ihrem Vuex-Store
  • Formularvalidierung
  • Datenvisualisierungen, die sich ändern, je nachdem, was der Benutzer sehen muss

Computed Properties sind ein wichtiger Teil von Vue, den man verstehen muss. Es sind Berechnungen, die basierend auf ihren Abhängigkeiten gecached werden und nur aktualisiert werden, wenn sie benötigt werden. Sie sind extrem performant, wenn sie gut eingesetzt werden, und außergewöhnlich nützlich. Es gibt viele große Bibliotheken, die diese Art von Logik handhaben und die Sie jetzt mit nur wenigen Codezeilen eliminieren können.

Computed Properties werden nicht wie Methoden verwendet, obwohl sie auf den ersten Blick ähnlich aussehen mögen – Sie geben eine Logik in einer Funktion an und geben etwas zurück – aber der **Name** dieser Funktion wird zu einer Eigenschaft, die Sie dann in Ihrer Anwendung wie data verwenden.

Wenn wir diese große Liste von Heldnamen basierend auf dem, was der Benutzer tippt, filtern müssten, würden wir es so tun. Wir halten dies sehr einfach, damit Sie die Grundkonzepte verstehen können. Ursprünglich würde unsere Liste in unserer Vorlage mit names ausgegeben, die wir in data speichern.

new Vue({
  el: '#app',
  data() {
    return {
      names: [
        'Evan You',
        'John Lindquist',
        'Jen Looper',
        'Miriam Suzanne',
        ...
      ]
    }
  }
})
<div id="app">
  <h1>Heroes</h1>
  <ul>
    <li v-for="name in names">
      {{ name }}
    </li>
  </ul>
</div>

Lassen Sie uns nun einen Filter für diese Namen erstellen. Wir beginnen mit der Erstellung eines Eingabefeldes mit v-model, das ursprünglich ein leerer String sein wird, aber wir werden es schließlich verwenden, um unsere Liste abzugleichen und zu filtern. Wir nennen diese Eigenschaft findName, und Sie können sie sowohl auf dem Eingabefeld als auch in den data referenziert sehen.

<label for="filtername">Find your hero:</label>
<input v-model="findName" id="filtername" type="text" />
data() {
  return {
    findName: '',
    names: [
      'Evan You',
      'John Lindquist',
      ...
    ]
  }
}

Nun können wir die **computed property** erstellen, die alle Namen basierend darauf filtert, was der Benutzer in das Eingabefeld eingegeben hat, also alles in unserer findName-Eigenschaft. Sie werden feststellen, dass ich hier Regex verwende, um sicherzustellen, dass Groß- und Kleinschreibung keine Rolle spielt, da Benutzer beim Tippen typischerweise nicht großschreiben.

computed: {
  filteredNames() {
    let filter = new RegExp(this.findName, 'i')
    return this.names.filter(el => el.match(filter))
  }
}

Und jetzt aktualisieren wir, was wir in der Vorlage verwenden, um dies auszugeben.

<ul>
  <li v-for="name in names">
    {{ name }}
  </li>
</ul>

...zu diesem:

<ul>
  <li v-for="name in filteredNames">
    {{ name }}
  </li>
</ul>

Und es filtert für uns bei jedem Tastendruck! Wir mussten nur ein paar Zeilen Code hinzufügen, um dies zu ermöglichen, und mussten keine zusätzlichen Bibliotheken laden.

Siehe den Pen Filter a list with Computed- end von Sarah Drasner (@sdras) auf CodePen.

Ich kann Ihnen gar nicht sagen, wie viel Zeit ich durch die Verwendung spare. Wenn Sie Vue verwenden und diese noch nicht erkundet haben, tun Sie es bitte, Sie werden es sich danken.

Watcher

Vue hat schöne Abstraktionen, und jeder, der schon länger programmiert, wird Ihnen normalerweise sagen, dass Abstraktionen eine Qual sein können, da sie schließlich auf einen Anwendungsfall stoßen, den sie nicht lösen können. Diese Situation ist jedoch berücksichtigt, da Vue uns tieferen Zugriff auf das Reaktivitätssystem gewährt, das wir als Hooks nutzen können, um alles zu beobachten, was sich ändert. Dies kann unglaublich nützlich sein, da wir als Anwendungsentwickler *für die meisten Dinge, für die wir verantwortlich sind, dafür sorgen, dass sich diese ändern*.

Watcher ermöglichen uns auch, deklarativeren Code zu schreiben. Sie verfolgen nicht mehr alles selbst. Vue erledigt dies bereits im Hintergrund, sodass Sie auch Zugriff auf Änderungen an allen Eigenschaften haben, die es verfolgt, z. B. in data, computed oder props.

Watcher eignen sich hervorragend für die Ausführung von Logik, die sich auf *etwas anderes* bezieht, wenn sich eine Eigenschaft ändert (ich habe diese Ausdrucksweise erstmals von Chris Fritz gehört, aber er sagt, er könnte sie auch von jemand anderem gehört haben ☺️). Dies ist keine harte Regel – Sie können Watcher absolut für Logik verwenden, die sich auf die Eigenschaft selbst bezieht, aber es ist eine nette Art, darüber nachzudenken, wie sich Watcher sofort von Computed Properties unterscheiden, bei denen die Änderung sich auf die Eigenschaft bezieht, die wir verwenden wollen.

Lassen Sie uns das einfachste mögliche Beispiel durchgehen, damit Sie einen Eindruck davon bekommen, was hier passiert.

new Vue({
  el: '#app', 
  data() {
    return {
      counter: 0
    }
  },
  watch: {
    counter() {
      console.log('The counter has changed!')
    }
  }
})

Wie Sie im obigen Code sehen können, speichern wir counter in data, und indem wir *den Namen der Eigenschaft als Funktionsnamen* verwenden, können wir ihn beobachten. Wenn wir diesen counter in watch referenzieren, können wir jede Änderung an dieser Eigenschaft beobachten.

Statuswechsel mit Watchern

Wenn der Status ähnlich genug ist, können Sie den Status sogar einfach mit Watchern wechseln. Hier ist ein Beispiel, das ich von Grund auf neu erstellt habe, eine Grafik mit Vue. Wenn sich die Daten ändern, aktualisieren die Watcher sie und wechseln einfach zwischen ihnen.

SVG ist auch gut für eine Aufgabe wie diese, da es auf Mathematik basiert.

Siehe den Pen Chart made with Vue, Transitioning State von Sarah Drasner (@sdras) auf CodePen.

watch: {
  selected: function(newValue, oldValue) {

    var tweenedData = {}

    var update = function () {
      let obj = Object.values(tweenedData);
      obj.pop();
      this.targetVal = obj;
    }

    var tweenSourceData = { onUpdate: update, onUpdateScope: this }

    for (let i = 0; i < oldValue.length; i++) {
      let key = i.toString()
      tweenedData[key] = oldValue[i]
      tweenSourceData[key] = newValue[i]
    }

    TweenMax.to(tweenedData, 1, tweenSourceData)
  }
}

Was ist hier passiert?

  • Zuerst haben wir ein Dummy-Objekt erstellt, das von unserer Animationsbibliothek aktualisiert wird.
  • Dann haben wir eine update-Funktion, die bei jedem Tween-Schritt aufgerufen wird. Wir verwenden diese, um die Daten zu pushen.
  • Dann erstellen wir ein Objekt, um die Quelldaten für das Tweening und den Funktionszeiger für Update-Ereignisse zu speichern.
  • Wir erstellen eine For-Schleife und wandeln den aktuellen Index in eine Zeichenkette um.
  • Dann können wir über unser Ziel-Dummy-Objekt tweeen, aber wir tun dies nur für den spezifischen Schlüssel.

Wir könnten auch Animationen in Watchern verwenden, um etwas wie diesen Zeitdifferenz-Regler zu erstellen. Ich reise viel und alle meine Kollegen sind in verschiedenen Gebieten, also wollte ich eine Möglichkeit haben, zu verfolgen, in welcher Zeitzone wir alle sind, sowie eine gewisse Kennzeichnung des Wechsels von Tag-/Nachtzeit.

Siehe den Pen Vue Time Comparison von Sarah Drasner (@sdras) auf CodePen.

Hier beobachten wir die checked-Eigenschaft und rufen verschiedene Methoden auf, die Timeline-Animationen enthalten, die die Farbton-, Sättigungs- und andere Elemente basierend auf der relativen Assoziation mit der aktuellen Zeit ändern. Wie bereits erwähnt – die Änderung erfolgt im Dropdown-Menü, *aber was wir ausführen, ist Logik, die woanders angewendet wird*.

watch: {
  checked() {
    let period = this.timeVal.slice(-2),
      hr = this.timeVal.slice(0, this.timeVal.indexOf(':'));

    const dayhr = 12,
      rpos = 115,
      rneg = -118;

    if ((period === 'AM' && hr != 12) || (period === 'PM' && hr == 12)) {
      this.spin(`${rneg - (rneg / dayhr) * hr}`)
      this.animTime(1 - hr / dayhr, period)
    } else {
      this.spin(`${(rpos / dayhr) * hr}`)
      this.animTime(hr / dayhr, period)
    }

  }
},

Es gibt auch eine Reihe anderer interessanter Dinge an Watchern, zum Beispiel: Wir erhalten Zugriff auf sowohl die neue als auch die alte Version der Eigenschaft als Parameter, wir können deep angeben, wenn wir ein verschachteltes Objekt beobachten möchten. Für detailliertere Informationen gibt es viele gute Informationen im Guide.

Sie können sehen, wie Watcher für alles, was sich aktualisiert – sei es Formulareingaben, asynchrone Aktualisierungen oder Animationen – unglaublich nützlich sein können. Wenn Sie neugierig sind, wie die Reaktivität in Vue funktioniert, ist dieser Teil des Guides wirklich hilfreich. Wenn Sie mehr über Reaktivität im Allgemeinen erfahren möchten, habe ich Andre Staltz' Post und den Reaktivitätsabschnitt von Mike Bostocks A Better Way to Code sehr genossen.

Zusammenfassend

Ich hoffe, dies war eine hilfreiche Aufschlüsselung, wie man jedes einzelne verwendet und Ihre Anwendungsentwicklung beschleunigt, indem Vue effizient genutzt wird. Es gibt eine Statistik, die besagt, dass wir als Programmierer 70% unserer Zeit mit Lesen von Code und 30% mit Schreiben verbringen. Persönlich liebe ich es, dass ich als Wartender eine Codebasis, die ich noch nie zuvor gesehen habe, ansehen und sofort verstehen kann, was der Autor durch die Unterscheidung zwischen methods, computed und watchers beabsichtigt hat.