Hinzufügen eines neuen To-do-Formulars: Vue-Ereignisse, Methoden und Modelle
Wir haben jetzt Beispieldaten bereitgestellt und eine Schleife, die jedes Datenstück nimmt und es in einem ToDoItem
in unserer App rendert. Was wir wirklich brauchen, ist die Fähigkeit, unseren Nutzern zu ermöglichen, ihre eigenen To-do-Elemente in die App einzugeben. Dazu 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, um die Daten zu steuern. Das werden wir in diesem Artikel behandeln.
Voraussetzungen: |
Vertrautheit mit den grundlegenden HTML, CSS, und JavaScript Sprachen, Kenntnis des Terminals/Befehlszeile. Vue-Komponenten werden als Kombination aus JavaScript-Objekten geschrieben, die die Daten der App verwalten, und einer HTML-basierten Vorlagensyntax, die der zugrundeliegenden DOM-Struktur zugeordnet ist. Für die Installation und die Nutzung einiger der fortschrittlicheren Funktionen von Vue (wie Single File Components oder Renderfunktionen) benötigen Sie ein Terminal mit installierten Node + npm. |
---|---|
Ziel: | Den Umgang mit Formularen in Vue zu lernen sowie damit verbunden Ereignisse, Modelle und Methoden. |
Erstellen eines neuen To-Do-Formulars
Wir haben jetzt eine App, die eine Liste von To-do-Elementen anzeigt. Wir können unsere Liste der Elemente jedoch nicht aktualisieren, ohne unseren Code manuell zu ändern! Lassen Sie uns das beheben. Erstellen Sie eine neue Komponente, die es uns ermöglicht, ein neues To-do-Element hinzuzufügen.
-
Erstellen Sie in Ihrem Komponentenordner eine neue Datei mit dem Namen
ToDoForm.vue
. -
Fügen Sie wie zuvor eine leere
<template>
- und eine<script>
-Tag hinzu:html<template></template> <script> export default {}; </script>
-
Fügen wir ein HTML-Formular hinzu, mit dem Sie ein neues To-do-Element eingeben und in die App einfügen können. Wir benötigen ein
<form>
mit einem<label>
, einem<input>
und einem<button>
. Aktualisieren Sie Ihr Template 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 ein Formular, in das wir den Titel eines neuen To-do-Elements eingeben können (der zum Etikett für das entsprechende
ToDoItem
wird, wenn es schließlich gerendert wird). -
Laden Sie diese Komponente in unsere App. Gehen Sie zurück zu
App.vue
und fügen Sie die folgendeimport
-Anweisung direkt unter der vorherigen ein, innerhalb Ihres<script>
-Elements:jsimport ToDoForm from "./components/ToDoForm.vue";
-
Sie müssen die neue Komponente auch in Ihrer
App
-Komponente registrieren — aktualisieren Sie diecomponents
-Eigenschaft des Komponentenobjekts, sodass sie wie folgt aussieht:jscomponents: { ToDoItem, ToDoForm, }
-
Rendern Sie abschließend in diesem Abschnitt Ihre
ToDoForm
-Komponente innerhalb Ihrer App, indem Sie das<to-do-form />
-Element innerhalb IhrerApp
-<template>
hinzufü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 anzeigen, sollten Sie das neue Formular angezeigt sehen.
Wenn Sie es ausfüllen und auf die Schaltfläche "Hinzufügen" klicken, wird die Seite das Formular zurück an den Server senden, aber das ist nicht wirklich das, was wir wollen. Was wir tatsächlich machen möchten, ist eine Methode beim submit
-Ereignis auszuführen, das das neue To-do zu der in App
definierten ToDoItem
-Datenliste hinzufügt. Dazu müssen wir der Komponenteninstanz eine Methode hinzufügen.
Erstellen einer Methode und Binden an ein Ereignis mit v-on
Um eine Methode in der ToDoForm
-Komponente verfügbar zu machen, müssen wir sie dem Komponentenobjekt hinzufügen, und zwar innerhalb einer methods
-Eigenschaft, 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. Beim Verweis werden Methoden vollständig ausgeführt, es ist daher keine gute Idee, sie zur Anzeige von Informationen innerhalb des Templates zu verwenden. Zum Anzeigen 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 Einreichungsaktion zu behandeln.Fügen Sie dies wie folgt 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 zum Binden von Attributen verwendet, hat Vue eine spezielle Direktive für die Ereignisbehandlung:v-on
. Diev-on
-Direktive funktioniert über diev-on:event="method"
-Syntax. Und ähnlich wiev-bind
, gibt es auch eine Kurzschreibweise:@event="method"
.Wir verwenden hier die Kurzschreibweise aus Konsistenzgründen. 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 weiterhin an den Server, was einen Refresh verursacht. Da wir all unsere Verarbeitung auf dem Client durchführen, gibt es keinen Server, der das Postback behandelt. Wir verlieren auch den gesamten lokalen Zustand beim Seitenrefresh. Um zu verhindern, dass der Browser an den Server sendet, müssen wir die Standardaktion des Ereignisses stoppen, während es durch die Seite hochbubbelt (
Event.preventDefault()
, in Vanilla JavaScript). Vue verfügt über eine spezielle Syntax namens Ereignismodifikatoren, die dies direkt in unserem Template für uns verarbeiten kann.Modifikatoren werden am Ende eines Ereignisses mit einem Punkt angehängt, z.B.:
@event.modifier
. Hier ist eine Liste der Ereignismodifikatoren:.stop
: Stoppt das Propagieren 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 von diesem genauen Element ausgelöst wurde.{.key}
: Löst den Ereignishandler nur über die angegebene Taste aus. MDN hat eine Liste gültiger Tastencodes; mehrteilige Tasten müssen nur in kebab-case konvertiert werden (z.B.page-down
)..native
: Lauscht auf ein natives Ereignis am Root- (äußerstes Wrapper-) Element Ihrer Komponente..once
: Lauscht auf das Ereignis, bis es einmalig ausgelöst wurde, danach 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 Eventlisteners in Vanilla JavaScript mitaddEventListener()
.
In diesem Fall müssen wir den
.prevent
-Modifikator verwenden, um die Standard-Sendeaktion des Browsers zu stoppen. Fügen Sie.prevent
zu dem@submit
-Handler in Ihrem Template wie folgt hinzu:html<form @submit.prevent="onSubmit">…</form>
Wenn Sie das Formular jetzt absenden, werden Sie feststellen, dass die Seite nicht neu lädt. Wenn Sie die Konsole öffnen, können Sie die Ergebnisse des in unserer onSubmit()
-Methode hinzugefügten console.log()
sehen.
Datenbindung an Eingaben mit v-model
Als Nächstes benötigen wir eine Möglichkeit, den Wert aus dem <input>
-Feld des Formulars zu erhalten, damit wir das neue To-do-Element zu 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 zu unseremToDoForm
-Komponentenobjekt hinzu, die einlabel
-Feld zurückgibt. Wir können den anfänglichen Wert deslabel
auf einen leeren String setzen.Ihr Komponentenobjekt sollte jetzt etwa so aussehen:
jsexport default { methods: { onSubmit() { console.log("form submitted"); }, }, data() { return { label: "", }; }, };
-
Nun brauchen wir eine Methode, um den Wert des
new-todo-input
-Elements an daslabel
-Feld zu binden. Vue hat dafür eine spezielle Direktive:v-model
.v-model
bindet an die Daten-Eigenschaft, die Sie darauf setzen und hält sie mit dem<input>
synchron.v-model
funktioniert bei allen verschiedenen Eingabetypen, einschließlich Kontrollkästchen, Radios und Auswahlfeldern. Umv-model
zu benutzen, 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 wie unten gezeigt hinzufügen. Machen Sie dies jetzt:html<input type="text" id="new-todo-input" name="new-todo" autocomplete="off" v-model="label" />
Hinweis: Sie können Daten auch mit
<input>
-Werten durch eine Kombination von Ereignissen undv-bind
-Attributen synchronisieren. Tatsächlich machtv-model
dies im Hintergrund. Die genaue Ereignis- und Attributkombination variiert jedoch je nach Eingabetypen und würde mehr Code erfordern als die einfache Verwendung derv-model
-Kurzschreibweise. -
Testen wir unsere Verwendung von
v-model
, indem wir den Wert der in unserer MethodeonSubmit()
übermittelten Daten protokollieren. In Komponenten werden Datenattribute unter Verwendung desthis
-Schlüsselworts zugegriffen. Daher greifen wir auf unserlabel
-Feld mitthis.label
zu.Aktualisieren Sie Ihre
onSubmit()
-Methode, damit sie so aussieht:jsmethods: { onSubmit() { console.log('Label value: ', this.label); } },
-
Gehen Sie nun zurück zu Ihrer laufenden App, geben Sie etwas Text in das
<input>
-Feld ein und klicken Sie auf den Button "Hinzufügen". Sie sollten den von Ihnen eingegebenen Wert in Ihre Konsole protokolliert sehen, zum Beispiel:Label value: My value
Ändern des v-model-Verhaltens mit Modifikatoren
In ähnlicher Weise 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 es zu berücksichtigen gilt. Der erste, .trim
, entfernt Leerzeichen vor oder nach der Eingabe. Wir können den Modifikator zu unserer v-model
-Anweisung wie folgt hinzufügen: v-model.trim="label"
.
Der zweite Modifikator, den wir in Betracht ziehen sollten, wird .lazy
genannt. Dieser Modifikator ändert, wann v-model
den Wert für Texteingaben synchronisiert. Wie bereits erwähnt, erfolgt die v-model
-Synchronisierung, indem die Variable mithilfe von Ereignissen aktualisiert wird. Bei Texteingaben erfolgt diese Synchronisation mithilfe des input
-Ereignisses. Oft bedeutet dies, dass Vue die Daten nach jedem Tastendruck synchronisiert. Der .lazy
-Modifikator bewirkt, dass v-model
das change
-Ereignis statt dessen verwendet. Dies bedeutet, dass Vue die Daten nur dann synchronisiert, wenn die Eingabe den Fokus verliert oder das Formular übermittelt wird. Für unsere Zwecke ist dies viel sinnvoller, 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 beispielsweise, einen Wert mit Leerzeichen an jedem Ende zu übermitteln.
Übergeben von Daten an übergeordnete Komponenten mit benutzerdefinierten Ereignissen
Wir sind jetzt 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. Dazu können wir unser ToDoForm
ein benutzerdefiniertes Ereignis auslösen lassen, das die Daten übergibt, und App
kann darauf hören. Dies funktioniert sehr ähnlich wie native Ereignisse bei HTML-Elementen: Eine Kindkomponente kann ein Ereignis auslösen, das über v-on
abgehört werden kann.
Im onSubmit
-Ereignishandler unseres ToDoForm
lassen Sie uns ein todo-added
-Ereignis hinzufügen. Benutzerdefinierte Ereignisse werden so ausgelöst: this.$emit("event-name")
. Es ist wichtig zu wissen, dass Ereignishandler case-sensitiv sind und keine Leerzeichen enthalten dürfen. Vue-Templates werden auch in Kleinbuchstaben konvertiert, was bedeutet, dass Vue-Templates nicht für Ereignisse mit Großbuchstaben zuhören können.
-
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 hinzugefügt
an die Konsole loggen.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 Ereignislistener für das
todo-added
-Ereignis zum<to-do-form></to-do-form>
hinzu, der dieaddToDo()
-Methode aufruft, wenn das Ereignis ausgelöst wird. Mit der@
-Kurzschreibung 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 aus deraddToDo()
-Methode sehen. Das ist gut, aber wir übergeben immer noch keine Daten zurück an dieApp.vue
-Komponente. Das können wir erreichen, indem wir zusätzliche Argumente an die Methodethis.$emit()
imToDoForm
-Modul übergeben.In diesem Fall möchten wir beim Auslösen des Ereignisses die
label
-Daten mit übergeben. Dies geschieht, indem Sie die Daten, die Sie übergeben möchten, als weiteren Parameter in die$emit()
-Methode einfügen:this.$emit("todo-added", this.label)
. Dies ähnelt dem, wie native JavaScript-Ereignisse Daten enthalten, außer dass benutzerdefinierte Vue-Ereignisse standardmäßig kein Ereignisobjekt enthalten. Das bedeutet, dass das ausgelöste Ereignis direkt dem Objekt entspricht, das Sie übergeben. In unserem Fall wird unser Ereignisobjekt also nur ein String sein.Aktualisieren Sie Ihre
onSubmit()
-Methode wie folgt:jsonSubmit() { this.$emit('todo-added', this.label) }
-
Um diese Daten tatsächlich in
App.vue
zu erfassen, müssen wir deraddToDo()
-Methode einen Parameter 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 in Ihrer Konsole protokolliert, sobald Sie es abschicken. Vue übergibt die Argumente nach dem Ereignisnamen in this.$emit()
automatisch an Ihren Ereignishandler.
Das neue To-do zu unseren Daten hinzufügen
Jetzt, da wir die Daten von ToDoForm
in App.vue
verfügbar haben, müssen wir ein Element, das diese darstellt, zum ToDoItems
-Array hinzufügen. Dies kann erreicht werden, indem wir ein neues To-do-Element-Objekt in das Array mit unseren neuen Daten hinzufügen.
-
Aktualisieren Sie Ihre
addToDo()
-Methode wie folgt:jsaddToDo(toDoLabel) { this.ToDoItems.push({id: "todo-" + nanoid(), label: toDoLabel, done: false}); }
-
Versuchen Sie, Ihr Formular erneut zu testen, 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 abschicken, während das Eingabefeld leer ist, werden To-do-Elemente ohne Text zur Liste hinzugefügt. Um das zu beheben, können wir verhindern, dass das
todo-added
-Ereignis bei leerem Name ausgelöst wird. Da der Name bereits vom.trim
-Modifikator geschnitten wird, müssen wir nur auf den leeren String testen.Kehren Sie zu Ihrer
ToDoForm
-Komponente zurück und aktualisieren Sie dieonSubmit()
-Methode wie folgt. Wenn der Label-Wert 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 können Sie keine leeren Elemente mehr zur To-do-Liste hinzufügen.
Verwenden von v-model zum Aktualisieren eines Eingabewerts
Es gibt noch etwas, das in unserer ToDoForm
-Komponente zu beheben ist — nach dem Absenden, enthält das <input>
immer noch den alten Wert. Aber das ist einfach zu beheben — weil wir v-model
verwenden, um die Daten an das <input>
in ToDoForm
zu binden, wird das Eingabefeld aktualisiert, wenn wir den Namen-Parameter auf einen leeren String setzen.
Aktualisieren Sie die onSubmit()
-Methode Ihrer ToDoForm
-Komponente auf Folgendes:
onSubmit() {
if (this.label === "") {
return;
}
this.$emit('todo-added', this.label);
this.label = "";
}
Jetzt, wenn Sie die Taste "Hinzufügen" klicken, wird die "new-todo-input" sich selbst leeren.
Zusammenfassung
Ausgezeichnet. Wir können jetzt To-do-Elemente zu unserem Formular hinzufügen! Unsere App beginnt jetzt interaktiv zu wirken, aber ein Problem ist, dass wir sein Aussehen und Gefühl bisher völlig ignoriert haben. Im nächsten Artikel konzentrieren wir uns darauf, dies zu beheben, und betrachten die verschiedenen Möglichkeiten, die Vue bereitstellt, um Komponenten zu stylen.