Hinzufügen eines neuen Todo-Formulars: Vue-Ereignisse, Methoden und Modelle
Wir haben jetzt Beispieldaten vorliegen und eine Schleife, die jedes Datenstück nimmt und in unserem App als ToDoItem rendert. Was wir wirklich als nächstes brauchen, ist die Möglichkeit, unseren Benutzern zu erlauben, ihre eigenen Todo-Einträge in die App einzugeben. Dafür benötigen wir ein Text-<input>, ein Ereignis, das ausgelöst wird, wenn die Daten übermittelt werden, eine Methode, die bei der Übermittlung ausgelöst wird, um die Daten hinzuzufügen und die Liste neu zu rendern, und ein Modell, das die Daten kontrolliert. Das ist das, was wir in diesem Artikel behandeln werden.
| Voraussetzungen: |
Vertrautheit mit den Kernsprachen HTML, CSS und JavaScript, Kenntnisse über das Terminal/Kommandozeile. 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 um einige der fortgeschritteneren Funktionen von Vue (wie Single File Components oder Render-Funktionen) zu nutzen, benötigen Sie ein Terminal mit installiertem Node + npm. |
|---|---|
| Ziel: | Erlernen des Umgangs mit Formularen in Vue und im Zusammenhang damit mit Ereignissen, Modellen und Methoden. |
Erstellen eines neuen To-Do-Formulars
Wir haben jetzt eine App, die eine Liste von To-Do-Einträgen anzeigt. Allerdings können wir unsere Liste nicht aktualisieren, ohne unseren Code manuell zu ändern! Lassen Sie uns das beheben. Lassen Sie uns eine neue Komponente erstellen, die es uns erlaubt, einen neuen To-Do-Eintrag hinzuzufügen.
-
Erstellen Sie in Ihrem Komponentenordner eine neue Datei namens
ToDoForm.vue. -
Fügen Sie wie zuvor einen leeren
<template>- und einen<script>-Tag hinzu:vue<template></template> <script> export default {}; </script> -
Lassen Sie uns ein HTML-Formular hinzufügen, das es Ihnen ermöglicht, ein neues Todo-Element einzugeben und in die App einzureichen. Wir brauchen ein
<form>mit einem<label>, einem<input>und einem<button>. Aktualisieren Sie Ihre Vorlage wie folgt:vue<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>So haben wir jetzt eine Formular-Komponente, in die wir den Titel eines neuen Todo-Elements eingeben können (das beim Rendern als Label für das entsprechende
ToDoItemdient). -
Laden Sie diese Komponente in unsere App. Gehen Sie zurück zu
App.vueund fügen Sie die folgendeimport-Anweisung direkt unterhalb der vorherigen innerhalb Ihres<script>-Elements hinzu:jsimport ToDoForm from "./components/ToDoForm.vue"; -
Sie müssen die neue Komponente auch in Ihrer
App-Komponente registrieren — aktualisieren Sie diecomponents-Eigenschaft des Komponentenobjekts, damit es so aussieht:jsexport default { // … components: { ToDoItem, ToDoForm, }, // … }; -
Schließlich, für diesen Abschnitt, rendern Sie Ihre
ToDoForm-Komponente in Ihrer App, indem Sie das<to-do-form />-Element innerhalb des<template>IhrerApphinzufügen, etwa so:vue<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 es ausfüllen und auf die Schaltfläche "Add" klicken, sendet die Seite das Formular zurück an den Server, aber das ist nicht wirklich das, was wir wollen. Was wir eigentlich tun möchten, ist eine Methode im submit-Ereignis auszuführen, die das neue Todo der ToDoItem-Datenliste hinzufügt, die in App definiert ist. Dafür müssen wir der Komponenteninstanz eine Methode hinzufügen.
Eine Methode erstellen und sie an ein Ereignis mit v-on binden
Um eine Methode in der ToDoForm-Komponente verfügbar zu machen, müssen wir sie dem Komponentenobjekt hinzufügen, und das geschieht in einer methods-Eigenschaft unserer Komponente, die an derselben Stelle wie data(), props usw. platziert wird. Die methods-Eigenschaft enthält alle Methoden, die wir möglicherweise in unserer Komponente aufrufen müssen. Wenn sie referenziert werden, laufen die Methoden vollständig ab, deshalb ist es keine gute Idee, sie zur Anzeige von Informationen innerhalb der Vorlage zu verwenden. Für die Darstellung 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 verwenden, um die Übermittlungsaktion zu handhaben.Fügen Sie dies so hinzu:
jsexport default { methods: { onSubmit() { console.log("form submitted"); }, }, }; -
Als nächstes müssen wir die Methode an den
submit-Ereignishandler unseres<form>-Elements binden. Ähnlich wie Vue diev-bind-Syntax für das Binden von Attributen verwendet, hat Vue eine spezielle Direktive für die Ereignisbehandlung:v-on. Diev-on-Direktive funktioniert über die Syntaxv-on:event="method". Und ähnlich wiev-bindgibt es auch eine Kurzsyntax:@event="method".Wir verwenden hier die Kurzsyntax für Konsistenz. Fügen Sie den
submit-Handler zu Ihrem<form>-Element hinzu, wie folgt:vue<form @submit="onSubmit">…</form> -
Wenn Sie dies ausführen, sendet die App die Daten immer noch an den Server, wodurch ein Refresh ausgelöst wird. Da wir alle unsere Verarbeitungen auf dem Client durchführen, gibt es keinen Server, der die Rückmeldung behandelt. Wir verlieren auch den gesamten lokalen Status bei einem Seiten-Refresh. Um zu verhindern, dass der Browser an den Server sendet, müssen wir die Standardaktion des Ereignisses stoppen, während es die Seite hinaufblubbert (
Event.preventDefault(), in Vanilla JavaScript). Vue hat eine spezielle Syntax namens Ereignis-Modifikatoren, die dies direkt in unserer Vorlage für uns erledigen kann.Modifikatoren werden am Ende eines Ereignisses mit einem Punkt angehängt, etwa so:
@event.modifier. Hier ist eine Liste von Ereignis-Modifikatoren:.stop: Stoppt das Ereignis vor der Weiterleitung. 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 von genau diesem Element gesendet wurde.{.key}: Löst den Ereignishandler nur über den angegebenen Schlüssel aus. MDN hat eine Liste gültiger Schlüsselwerte; mehrwortige Schlüssel müssen einfach in kebab-case umgewandelt werden (z. B.page-down)..native: Lauscht auf ein natives Ereignis am Wurzelelement (äußerst umhüllendes) 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 Parameters{ passive: true }beim Erstellen eines Ereignislisteners in Vanilla JavaScript, dasaddEventListener()verwendet.
In diesem Fall müssen wir den Modifikator
.preventverwenden, um die Standard-Submit-Aktion des Browsers zu stoppen. Fügen Sie.preventzu dem@submit-Handler in Ihrer Vorlage wie folgt hinzu:vue<form @submit.prevent="onSubmit">…</form>
Wenn Sie versuchen, das Formular jetzt zu übermitteln, werden Sie feststellen, dass sich die Seite nicht neu lädt. Wenn Sie die Konsole öffnen, können Sie die Ergebnisse des console.log() sehen, das wir in unserer onSubmit()-Methode hinzugefügt haben.
Daten mit v-model an Eingaben binden
Als nächstes benötigen wir eine Möglichkeit, den Wert aus dem <input>-Formularfeld 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 Todos zu verfolgen.
-
Fügen Sie unserem
ToDoForm-Komponentenobjekt einedata()-Methode hinzu, die einlabel-Feld zurückgibt. Wir können den Anfangswert deslabelauf eine leere Zeichenkette setzen.Ihr Komponentenobjekt sollte jetzt ungefähr so aussehen:
jsexport default { methods: { onSubmit() { console.log("form submitted"); }, }, data() { return { label: "", }; }, }; -
Wir benötigen nun eine Möglichkeit, den Wert des
new-todo-input-Element zu demlabel-Feld zu verknüpfen. Vue hat eine spezielle Direktive dafür:v-model.v-modelbindet an die Daten-Eigenschaft, die Sie darauf setzen, und hält sie mit dem<input>synchron.v-modelfunktioniert über alle verschiedenen Eingabetypen hinweg, einschließlich Kontrollkästchen, Radios und Auswahlfelder. Umv-modelzu verwenden, fügen Sie dem<input>ein Attribut mit der Strukturv-model="variable"hinzu.In unserem Fall würden wir es auf unserem
new-todo-input-Feld wie unten gesehen hinzufügen. Machen Sie dies jetzt:vue<input type="text" id="new-todo-input" name="new-todo" autocomplete="off" v-model="label" />Hinweis: Sie können Daten mit
<input>-Werten auch über eine Kombination von Ereignissen undv-bind-Attributen synchronisieren. Tatsächlich machtv-modeldies hinter den Kulissen. Allerdings variiert die genaue Ereignis- und Attributkombination je nach Eingabetypen und benötigt mehr Code als die Nutzung derv-model-Abkürzung. -
Lassen Sie uns unsere Verwendung von
v-modeltesten, indem wir den Wert der übermittelten Daten in unsereronSubmit()-Methode protokollieren. In Komponenten werden Datenattribute über dasthis-Schlüsselwort zugegriffen. Daher greifen wir auf unserlabel-Feld mitthis.labelzu.Aktualisieren Sie Ihre
onSubmit()-Methode, sodass sie wie folgt aussieht:jsexport default { methods: { onSubmit() { console.log("Label value: ", this.label); }, }, }; -
Gehen Sie jetzt zurück zu Ihrer laufenden App, fügen Sie dem
<input>-Feld einen Text hinzu und klicken Sie auf die Schaltfläche "Add". Sie sollten den von Ihnen eingegebenen Wert in Ihrer Konsole protokolliert sehen, zum Beispiel:Label value: My value
Verhalten von v-model mit Modifikatoren ändern
Ähnlich zu Ereignis-Modifikatoren können wir auch Modifikatoren hinzufügen, um das Verhalten von v-model zu ändern. In unserem Fall sind zwei Modifikatoren einen Blick wert. Der erste, .trim, entfernt Leerzeichen vor oder nach der Eingabe. Wir können den Modifikator zu unserem v-model-Statement hinzufügen: 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 vorher erwähnt, funktioniert die v-model-Synchronisation, indem die Variable mit Ereignissen aktualisiert wird. Für Texteingaben erfolgt diese Synchronisation über das 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 die Daten nur synchronisiert, wenn die Eingabe den Fokus verliert oder das Formular übermittelt 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 gemeinsam 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 dann Ihre App erneut. Versuchen Sie z. B., einen Wert mit Leerzeichen an jedem Ende einzugeben.
Daten an Elternkomponenten mit benutzerdefinierten Ereignissen übergeben
Wir sind nun sehr nahe daran, neue To-Do-Einträge unserer Liste hinzuzufügen. Als nächstes müssen wir in der Lage sein, den neu erstellten To-Do-Eintrag an unsere App-Komponente zu übergeben. Dazu kann unsere ToDoForm ein benutzerdefiniertes Ereignis senden, das die Daten übergibt, und App kann darauf hören. Dies funktioniert ähnlich wie native Ereignisse auf HTML-Elementen: eine Kinderkomponente kann ein Ereignis senden, das über v-on abgehört werden kann.
Im onSubmit-Ereignishandler unserer ToDoForm fügen wir ein todo-added-Ereignis hinzu. Benutzerdefinierte Ereignisse werden so gesendet: this.$emit("event-name"). Wichtig zu wissen ist, dass Ereignishandler Groß- und Kleinschreibung beachten und keine Leerzeichen enthalten können. Vue-Vorlagen werden auch in Kleinschreibung umgewandelt, was bedeutet, dass Vue-Vorlagen keine Ereignisse mit Großbuchstaben hören können.
-
Ersetzen Sie das
console.log()in deronSubmit()-Methode mit dem folgenden:jsthis.$emit("todo-added"); -
Gehen Sie als nächstes zurück zu
App.vueund fügen Sie einemethods-Eigenschaft zu Ihrem Komponentenobjekt hinzu, die eineaddToDo()-Methode enthält, wie unten gezeigt. Diese Methode kann vorerst einfachTo-do addedin 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 nun ein Ereignislistener für das
todo-added-Ereignis zum<to-do-form></to-do-form>hinzu, das dieaddToDo()-Methode aufruft, wenn das Ereignis ausgelöst wird. Mithilfe der@-Kurzschreibweise sieht der Listener so aus:@todo-added="addToDo":vue<to-do-form @todo-added="addToDo"></to-do-form> -
Wenn Sie Ihr
ToDoFormabschicken, sollten Sie das Konsolenprotokoll von deraddToDo()-Methode sehen. Das ist gut, aber wir übergeben noch keine Daten zurück an dieApp.vue-Komponente. Das können wir tun, indem wir zusätzliche Argumente an diethis.$emit()-Funktion in derToDoForm-Komponente übergeben.In diesem Fall, wenn wir das Ereignis auslösen, möchten wir die
label-Daten damit übergeben. Das wird gemacht, indem man die Daten, die man übergeben möchte, als weiterer Parameter in der$emit()-Methode einfügt: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 gesendete Ereignis genau mit dem Objekt übereinstimmt, das Sie übermitteln. In unserem Fall wird unser Ereignisobjekt nur eine Zeichenkette sein.Aktualisieren Sie Ihre
onSubmit()-Methode so:jsexport default { // … methods: { // … onSubmit() { this.$emit("todo-added", this.label); }, // … }, // … }; -
Um diese Daten in der
App.vuetatsächlich zu erfassen, müssen wir demaddToDo()-Methode ein Parameter hinzufügen, das daslabeldes neuen To-Do-Elements enthält.Gehen Sie zurück zu
App.vueund aktualisieren Sie dies jetzt:jsexport default { // … methods: { // … addToDo(toDoLabel) { console.log("To-do added:", toDoLabel); }, // … }, // … };
Wenn Sie Ihr Formular erneut testen, sehen Sie, dass der Text, den Sie bei der Übermittlung eingegeben haben, in Ihrer Konsole protokolliert wird. Vue übergibt die Argumente nach dem Ereignisnamen in this.$emit() automatisch an Ihren Ereignishandler.
Das neue To-Do in unsere Daten hinzufügen
Jetzt, da wir die Daten von ToDoForm in App.vue zur Verfügung haben, müssen wir dem ToDoItems-Array ein Element hinzufügen, das sie repräsentiert. Dies kann geschehen, indem man ein neues To-Do-Objekt zum Array hinzufügt, das unsere neuen Daten enthält.
-
Aktualisieren Sie Ihre
addToDo()-Methode wie folgt:jsexport default { // … methods: { // … addToDo(toDoLabel) { this.ToDoItems.push({ id: `todo-${nanoid()}`, label: toDoLabel, done: false, }); }, // … }, // … }; -
Versuchen Sie, Ihr Formular wieder zu testen, und Sie sollten sehen, wie neue To-Do-Elemente am Ende der Liste angefügt werden.
-
Lassen Sie uns eine weitere Verbesserung vornehmen, bevor wir fortfahren. Wenn Sie das Formular übermitteln, während die Eingabe leer ist, werden noch immer To-Do-Elemente ohne Text zur Liste hinzugefügt. Um das zu beheben, können wir verhindern, dass das
todo-added-Ereignis ausgelöst wird, wenn der Name leer ist. Da der Name bereits vom.trim-Modifikator getrimmt wird, müssen wir nur auf die leere Zeichenkette testen.Gehen Sie zurück zu Ihrer
ToDoForm-Komponente, und aktualisieren Sie dieonSubmit()-Methode wie folgt. Wenn derlabel-Wert leer ist, lassen Sie uns dastodo-added-Ereignis nicht senden.jsexport default { // … methods: { // … onSubmit() { if (this.label === "") { return; } this.$emit("todo-added", this.label); }, // … }, // … }; -
Versuchen Sie Ihr Formular erneut. Jetzt werden Sie keine leeren Elemente mehr zur To-Do-Liste hinzufügen können.

Verwenden von v-model zur Aktualisierung eines Eingabewerts
Es gibt eine weitere Sache, die wir in unserer ToDoForm-Komponente beheben müssen — nach der Übermittlung enthält das <input>-Feld immer noch den alten Wert. Aber das ist einfach zu beheben — da wir v-model verwenden, um die Daten an das <input> in ToDoForm zu binden, wenn wir den name-Parameter auf eine leere Zeichenkette setzen, wird das Eingabefeld ebenfalls aktualisiert.
Aktualisieren Sie die onSubmit()-Methode Ihrer ToDoForm-Komponente zu folgendem:
export default {
// …
methods: {
// …
onSubmit() {
if (this.label === "") {
return;
}
this.$emit("todo-added", this.label);
this.label = "";
},
// …
},
// …
};
Nun wird beim Klicken auf die Schaltfläche "Add" die "new-todo-input" sich selbst leeren.
Zusammenfassung
Ausgezeichnet. Wir können jetzt ToDo-Elemente zu unserem Formular hinzufügen! Unsere App beginnt jetzt interaktiv zu wirken, aber ein Problem ist, dass wir ihr Aussehen und Gefühl bisher komplett ignoriert haben. Im nächsten Artikel konzentrieren wir uns auf die Behebung dieses Problems, indem wir die verschiedenen Möglichkeiten untersuchen, die Vue zur Stilisierung von Komponenten bietet.