Hinzufügen eines neuen Todo-Formulars: Vue-Ereignisse, Methoden und Modelle
Wir haben nun Beispieldaten integriert und eine Schleife, die jedes Datenstück nimmt und es innerhalb eines ToDoItem
in unserer App rendert. Was wir als nächstes wirklich brauchen, ist die Möglichkeit für unsere Benutzer, ihre eigenen Todo-Elemente in die App einzugeben. Dafür benötigen wir ein Text-<input>
, ein Ereignis, das beim Absenden der Daten ausgelöst wird, eine Methode, die beim Absenden ausgeführt wird, um die Daten hinzuzufügen und die Liste neu zu rendern, sowie ein Modell zur Steuerung der Daten. Dies werden wir in diesem Artikel behandeln.
Voraussetzungen: |
Vertrautheit mit den grundlegenden HTML, CSS und JavaScript Sprachen, Kenntnisse über die Terminal/Kommandzeile. Vue-Komponenten werden als Kombination aus JavaScript-Objekten geschrieben, die die Daten der App verwalten, und einer HTML-basierten Vorlagensyntax, die auf die zugrunde liegende DOM-Struktur abbildet. Für die Installation und Nutzung einiger der fortgeschritteneren Funktionen von Vue (wie Einzeldateikomponenten oder Renderfunktionen), benötigen Sie ein Terminal mit installierten Node + npm. |
---|---|
Ziel: | Um das Arbeiten mit Formularen in Vue zu erlernen und damit verbunden Ereignisse, Modelle und Methoden. |
Erstellen eines neuen To-Do Formulars
Wir haben nun eine App, die eine Liste von Aufgaben anzeigt. Allerdings können wir unsere Liste der Elemente nicht aktualisieren, ohne unseren Code manuell zu ändern! Das wollen wir beheben. Lassen Sie uns eine neue Komponente erstellen, die es erlaubt, ein neues To-Do-Element hinzuzufügen.
-
Erstellen Sie in Ihrem Komponentenordner eine neue Datei namens
ToDoForm.vue
. -
Fügen Sie wie zuvor ein leeres
<template>
und<script>
-Tag hinzu:html<template></template> <script> export default {}; </script>
-
Lassen Sie uns ein HTML-Formular hinzufügen, das die Eingabe eines neuen Todo-Elements ermöglicht und es in die App einfügt. Wir benötigen ein
<form>
mit einem<label>
, einem<input>
und einem<button>
. Aktualisieren Sie Ihre Vorlage wie folgt:html<template> <form> <label for="new-todo-input"> What needs to be done? </label> <input type="text" id="new-todo-input" name="new-todo" autocomplete="off" /> <button type="submit">Add</button> </form> </template>
Wir haben jetzt also eine Formular-Komponente, in die wir den Titel eines neuen Todo-Elements eingeben können (welcher letztlich als Beschriftung für das entsprechende
ToDoItem
dient, wenn es gerendert wird). -
Lassen Sie uns diese Komponente in unsere App laden. Gehen Sie zurück zu
App.vue
und fügen Sie die folgendeimport
-Anweisung direkt unter der vorherigen im<script>
-Element hinzu:jsimport ToDoForm from "./components/ToDoForm.vue";
-
Sie müssen auch die neue Komponente in Ihrer
App
-Komponente registrieren – aktualisieren Sie diecomponents
-Eigenschaft des Komponentenobjekts, sodass es so aussieht:jscomponents: { ToDoItem, ToDoForm, }
-
Rendern Sie abschließend für diesen Abschnitt Ihre
ToDoForm
-Komponente, indem Sie das<to-do-form />
-Element in das<template>
IhrerApp
einfügen, wie folgt:html<template> <div id="app"> <h1>My To-Do List</h1> <to-do-form></to-do-form> <ul> <li v-for="item in ToDoItems" :key="item.id"> <to-do-item :label="item.label" :done="item.done" :id="item.id"></to-do-item> </li> </ul> </div> </template>
Wenn Sie nun Ihre laufende Seite ansehen, sollten Sie das neue Formular angezeigt sehen.
Wenn Sie das Formular ausfüllen und auf die Schaltfläche "Hinzufügen" klicken, wird das Formular zurück an den Server gesendet, aber genau das wollen wir eigentlich nicht. Stattdessen möchten wir, dass eine Methode beim submit
-Ereignis ausgeführt wird, die das neue Todo dem in App
definierten ToDoItem
-Datenliste hinzufügt. Dafür müssen wir eine Methode zur Komponenteninstanz hinzufügen.
Erstellen einer Methode & Verknüpfen mit einem Ereignis mit v-on
Um eine Methode für die ToDoForm
-Komponente bereitzustellen, müssen wir sie zum Komponentenobjekt hinzufügen. Dies geschieht innerhalb einer methods
-Eigenschaft unserer Komponente, die sich an derselben Stelle befindet wie data()
, props
usw. Die methods
-Eigenschaft enthält alle Methoden, die wir möglicherweise in unserer Komponente aufrufen müssen. Wenn Methoden referenziert werden, laufen sie vollständig ab, daher ist es keine gute Idee, sie zum Anzeigen von Informationen innerhalb der Vorlage zu verwenden. Für die Anzeige von Daten, die aus Berechnungen stammen, sollten Sie eine computed
-Eigenschaft verwenden, die wir später behandeln werden.
-
In dieser Komponente müssen wir eine
onSubmit()
-Methode zu einermethods
-Eigenschaft innerhalb desToDoForm
-Komponentenobjekts hinzufügen. Wir werden diese Methode verwenden, um die Absendeaktion zu behandeln.Fügen Sie diese wie folgt hinzu:
jsexport default { methods: { onSubmit() { console.log("form submitted"); }, }, };
-
Als nächstes müssen wir die Methode mit dem
submit
-Ereignis-Handler des<form>
-Elements verknüpfen. Ähnlich wie Vue diev-bind
-Syntax für die Attributbindung verwendet, hat Vue eine spezielle Direktive für die Ereignisbehandlung:v-on
. Diev-on
-Direktive funktioniert über diev-on:event="method"
-Syntax. Und ähnlich wie beiv-bind
gibt es auch eine Kurzsyntax:@event="method"
.Wir verwenden hier die Kurzsyntax der Konsistenz halber. Fügen Sie den
submit
-Handler zu Ihrem<form>
-Element wie folgt hinzu:html<form @submit="onSubmit">…</form>
-
Wenn Sie dies ausführen, sendet die App die Daten immer noch an den Server, was zu einem Neuladen führt. Da wir alle unsere Verarbeitung auf dem Client durchführen, gibt es keinen Server, der die Rücksendung behandelt. Wir verlieren auch alle lokalen Zustände beim Seitenaktualisieren. Um zu verhindern, dass der Browser an den Server postet, müssen wir die Standardaktion des Ereignisses stoppen, während es durch die Seite läuft (
Event.preventDefault()
in Vanilla JavaScript). Vue hat eine spezielle Syntax namens Ereignismodifikatoren, die dies für uns direkt in unserer Vorlage handhaben kann.Modifikatoren werden am Ende eines Ereignisses mit einem Punkt wie folgt angehängt:
@event.modifier
. Hier ist eine Liste von Ereignismodifikatoren:.stop
: Stoppt die Ausbreitung des Ereignisses. EntsprichtEvent.stopPropagation()
in regulären JavaScript-Ereignissen..prevent
: Verhindert das Standardverhalten des Ereignisses. EntsprichtEvent.preventDefault()
..self
: Löst den Handler nur aus, wenn das Ereignis genau von diesem Element ausgelöst wurde.{.key}
: Löst den Ereignishandler nur über die angegebene Taste aus. MDN hat eine Liste gültiger Tastenwerte; mehrwortige Tasten müssen nur in kebab-case umgewandelt werden (z. B.page-down
)..native
: Lauscht auf ein natives Ereignis auf dem Wurzel- (äußersten) Wrapper-Element Ihrer Komponente..once
: Lauscht auf das Ereignis, bis es einmal ausgelöst wurde und dann nicht mehr..left
: Löst den Handler nur über das linke Maustastenereignis aus..right
: Löst den Handler nur über das rechte Maustastenereignis aus..middle
: Löst den Handler nur über das mittlere Maustastenereignis aus..passive
: Entspricht der Verwendung des{ passive: true }
-Parameters beim Erstellen eines Ereignislisteners in Vanilla JavaScript mitaddEventListener()
.
In diesem Fall müssen wir den
.prevent
-Modifikator verwenden, um die Standardaktion des Browsers bei der Übermittlung zu stoppen. Fügen Sie.prevent
zu Ihrem@submit
-Handler in Ihrer Vorlage wie folgt hinzu:html<form @submit.prevent="onSubmit">…</form>
Wenn Sie versuchen, das Formular jetzt abzusenden, werden Sie feststellen, dass die Seite nicht neu geladen wird. Wenn Sie die Konsole öffnen, können Sie die Ergebnisse des von uns hinzugefügten console.log()
in unserer onSubmit()
-Methode sehen.
Datenbindung an Eingaben mit v-model
Als nächstes benötigen wir eine Möglichkeit, den Wert aus dem <input>
des Formulars zu erhalten, damit wir das neue To-Do-Element unserer ToDoItems
-Datenliste hinzufügen können.
Das erste, was wir benötigen, ist eine data
-Eigenschaft in unserem Formular, um den Wert des To-Dos zu verfolgen.
-
Fügen Sie eine
data()
-Methode zumToDoForm
-Komponentenobjekt hinzu, die einlabel
-Feld zurückgibt. Wir können den Anfangswert deslabel
auf einen leeren String setzen.Ihr Komponentenobjekt sollte nun so aussehen:
jsexport default { methods: { onSubmit() { console.log("form submitted"); }, }, data() { return { label: "", }; }, };
-
Nun benötigen wir eine Möglichkeit, den Wert des
new-todo-input
-Feldes an daslabel
-Feld zu binden. Vue hat dafür eine spezielle Direktive:v-model
.v-model
bindet sich an die Dateneigenschaft, die Sie setzen, und hält sie mit dem<input>
synchron.v-model
funktioniert bei allen verschiedenen Eingabetypen, einschließlich Kontrollkästchen, Radios und Auswahlfelder. Umv-model
zu verwenden, fügen Sie ein Attribut mit der Strukturv-model="variable"
zum<input>
hinzu.In unserem Fall würden wir es zu unserem
new-todo-input
-Feld hinzufügen, wie unten gezeigt. Machen Sie dies jetzt:html<input type="text" id="new-todo-input" name="new-todo" autocomplete="off" v-model="label" />
Hinweis: Sie können
<input>
-Werte auch durch eine Kombination von Ereignissen undv-bind
-Attributen synchronisieren. Tatsächlich macht genau dasv-model
hinter den Kulissen. Die genaue Kombination von Ereignis und Attribut variiert jedoch je nach Eingabetypen und erfordert mehr Code als nur die Verwendung derv-model
-Abkürzung. -
Lassen Sie uns unsere Nutzung von
v-model
testen, indem wir den Wert der Daten in unsereronSubmit()
-Methode protokollieren. In Komponenten werden Datenattribute mit dem Schlüsselwortthis
zugegriffen. Also greifen wir auf unserlabel
-Feld mitthis.label
zu.Aktualisieren Sie Ihre
onSubmit()
-Methode so, dass sie wie folgt aussieht:jsmethods: { onSubmit() { console.log('Label value: ', this.label); } },
-
Gehen Sie nun zurück zu Ihrer laufenden App, fügen Sie etwas Text in das
<input>
-Feld ein und klicken Sie auf die Schaltfläche "Hinzufügen". Sie sollten den von Ihnen eingegebenen Wert in Ihrer Konsole protokolliert sehen, zum Beispiel:Label value: My value
Ändern des v-model Verhaltens mit Modifikatoren
Ähnlich wie bei Ereignismodifikatoren können wir auch Modifikatoren hinzufügen, um das Verhalten von v-model
zu ändern. In unserem Fall gibt es zwei, die wir in Betracht ziehen sollten. Der erste, .trim
, entfernt den Leerraum vor oder nach der Eingabe. Wir können den Modifikator zu unserer v-model
-Anweisung hinzufügen, so: v-model.trim="label"
.
Der zweite Modifikator, den wir in Betracht ziehen sollten, heißt .lazy
. Dieser Modifikator ändert, wann v-model
den Wert für Texteingaben synchronisiert. Wie bereits erwähnt, funktioniert die v-model
-Synchronisierung, indem die Variable mit Ereignissen aktualisiert wird. Für Texteingaben geschieht diese Synchronisierung mit dem input
-Ereignis. Oft bedeutet dies, dass Vue die Daten nach jedem Tastenanschlag synchronisiert. Der .lazy
-Modifikator bewirkt, dass v-model
stattdessen das change
-Ereignis verwendet. Das bedeutet, dass Vue Daten nur synchronisiert, wenn die Eingabe den Fokus verliert oder das Formular abgeschickt wird. Für unsere Zwecke ist dies viel angemessener, da wir nur die endgültigen Daten benötigen.
Um sowohl den .lazy
-Modifikator als auch den .trim
-Modifikator zusammen zu verwenden, können wir sie verketten, z. B. v-model.lazy.trim="label"
.
Aktualisieren Sie Ihr v-model
-Attribut, um lazy
und trim
wie oben gezeigt zu verketten, und testen Sie Ihre App erneut. Versuchen Sie zum Beispiel, einen Wert mit Leerzeichen an jedem Ende einzusenden.
Datenübergabe an Eltern mit benutzerdefinierten Ereignissen
Wir sind nun sehr nah dran, neue To-Do-Elemente zu unserer Liste hinzuzufügen. Das nächste, was wir tun müssen, ist, das neu erstellte To-Do-Element an unsere App
-Komponente zu übergeben. Dafür kann unsere ToDoForm
ein benutzerdefiniertes Ereignis auslösen, das die Daten weitergibt, und App
kann darauf achten. Dies funktioniert sehr ähnlich wie native Ereignisse auf HTML-Elementen: Eine Kindkomponente kann ein Ereignis auslösen, das über v-on
überwacht werden kann.
Im onSubmit
-Ereignishandler unserer ToDoForm
fügen wir ein todo-added
-Ereignis hinzu. Benutzerdefinierte Ereignisse werden wie folgt ausgelöst: this.$emit("event-name")
. Es ist wichtig zu wissen, dass Ereignishandler case-sensitive sind und keine Leerzeichen enthalten dürfen. Vue-Vorlagen werden ebenfalls in Kleinbuchstaben umgewandelt, was bedeutet, dass Vue-Vorlagen nicht auf Ereignisse hören können, die mit Großbuchstaben benannt sind.
-
Ersetzen Sie das
console.log()
in deronSubmit()
-Methode durch Folgendes:jsthis.$emit("todo-added");
-
Gehen Sie als nächstes zurück zu
App.vue
und fügen Sie einemethods
-Eigenschaft zu Ihrem Komponentenobjekt hinzu, die eineaddToDo()
-Methode enthält, wie unten gezeigt. Diese Methode kann vorerst einfachTo-do added
in die Konsole protokollieren.jsexport default { name: "app", components: { ToDoItem, ToDoForm, }, data() { return { ToDoItems: [ { id: "todo-" + nanoid(), label: "Learn Vue", done: false }, { id: "todo-" + nanoid(), label: "Create a Vue project with the CLI", done: true, }, { id: "todo-" + nanoid(), label: "Have fun", done: true }, { id: "todo-" + nanoid(), label: "Create a to-do list", done: false, }, ], }; }, methods: { addToDo() { console.log("To-do added"); }, }, };
-
Fügen Sie als Nächstes einen Ereignis-Listener für das
todo-added
-Ereignis zum<to-do-form></to-do-form>
-Element hinzu, das dieaddToDo()
-Methode aufruft, wenn das Ereignis ausgelöst wird. Mit der Kurzsyntax@
würde der Listener so aussehen:@todo-added="addToDo"
:html<to-do-form @todo-added="addToDo"></to-do-form>
-
Wenn Sie Ihr
ToDoForm
absenden, sollten Sie das Konsolenprotokoll deraddToDo()
-Methode sehen. Das ist gut, aber wir geben immer noch keine Daten zurück an dieApp.vue
-Komponente. Das können wir tun, indem wir zusätzliche Argumente an diethis.$emit()
-Funktion zurück in derToDoForm
-Komponente übergeben.In diesem Fall möchten wir, wenn wir das Ereignis auslösen, die
label
-Daten mit übergeben. Dies erfolgt durch das Hinzufügen der Daten, die Sie übergeben möchten, als weiteren Parameter in der$emit()
-Methode:this.$emit("todo-added", this.label)
. Dies ist ähnlich wie bei nativen JavaScript-Ereignissen, die Daten enthalten, außer dass benutzerdefinierte Vue-Ereignisse standardmäßig kein Ereignisobjekt enthalten. Das bedeutet, dass das ausgegebene Ereignis direkt mit dem von Ihnen übergegebenen Objekt übereinstimmt. In unserem Fall wird unser Ereignisobjekt also einfach eine Zeichenkette sein.Aktualisieren Sie Ihre
onSubmit()
-Methode so:jsonSubmit() { this.$emit('todo-added', this.label) }
-
Um diese Daten in
App.vue
tatsächlich zu erfassen, müssen wir einen Parameter zu unsereraddToDo()
-Methode hinzufügen, der daslabel
des neuen To-Do-Elements enthält.Gehen Sie zurück zu
App.vue
und aktualisieren Sie dies jetzt:jsmethods: { addToDo(toDoLabel) { console.log('To-do added:', toDoLabel); } }
Wenn Sie Ihr Formular erneut testen, sehen Sie den von Ihnen eingegebenen Text bei der Übermittlung in Ihrer Konsole protokolliert. Vue übergibt automatisch die Argumente nach dem Ereignisnamen in this.$emit()
an Ihren Ereignishandler.
Hinzufügen des neuen Todos in unsere Daten
Jetzt, da wir die Daten aus dem ToDoForm
in App.vue
verfügbar haben, müssen wir ein Element erstellen, das es der ToDoItems
-Liste hinzufügt. Dies kann erfolgen, indem wir ein neues Todo-Objekt zur Liste hinzufügen, das unsere neuen Daten enthält.
-
Aktualisieren Sie Ihre
addToDo()
-Methode so:jsaddToDo(toDoLabel) { this.ToDoItems.push({id: "todo-" + nanoid(), label: toDoLabel, done: false}); }
-
Testen Sie Ihr Formular erneut, und Sie sollten sehen, dass neue To-Do-Elemente am Ende der Liste angehängt werden.
-
Lassen Sie uns eine weitere Verbesserung vornehmen, bevor wir weitermachen. Wenn Sie das Formular absenden, während die Eingabe leer ist, werden Todo-Elemente ohne Text immer noch zur Liste hinzugefügt. Um dies zu beheben, können wir verhindern, dass das todo-added-Ereignis ausgelöst wird, wenn der Name leer ist. Da der Name bereits durch den
.trim
-Modifikator beschnitten wird, müssen wir nur auf den leeren String testen.Gehen Sie zurück zu Ihrer
ToDoForm
-Komponente und aktualisieren Sie dieonSubmit()
-Methode wie folgt. Wenn der Labelwert leer ist, lassen Sie uns dastodo-added
-Ereignis nicht auslösen.jsonSubmit() { if (this.label === "") { return; } this.$emit('todo-added', this.label); }
-
Testen Sie Ihr Formular erneut. Jetzt wird es nicht mehr möglich sein, leere Elemente zur Todo-Liste hinzuzufügen.
Verwenden von v-model zum Aktualisieren eines Eingabewerts
Es gibt noch eine Sache, die wir in unserer ToDoForm
-Komponente beheben müssen — nach dem Senden enthält das <input>
immer noch den alten Wert. Aber das ist einfach zu beheben — da wir v-model
zum Binden der Daten an das <input>
in ToDoForm
verwenden, wenn wir den Namen auf einen leeren String setzen, wird die Eingabe ebenfalls aktualisiert.
Aktualisieren Sie die onSubmit()
-Methode der ToDoForm
-Komponente zu folgendem:
onSubmit() {
if (this.label === "") {
return;
}
this.$emit('todo-added', this.label);
this.label = "";
}
Nun, wenn Sie auf die Schaltfläche "Hinzufügen" klicken, wird das "new-todo-input" sich selbst leeren.
Zusammenfassung
Ausgezeichnet. Wir können nun Todo-Elemente zu unserem Formular hinzufügen! Unsere App beginnt nun, interaktiv zu wirken, aber ein Problem bleibt, dass wir das Erscheinungsbild völlig ignoriert haben. Im nächsten Artikel werden wir uns darauf konzentrieren, dies zu beheben, indem wir uns die verschiedenen Möglichkeiten ansehen, die Vue zur Verfügung stellt, um Komponenten zu stylen.