Dynamisches Verhalten in Svelte: Arbeiten mit Variablen und Props
Da wir nun unser Markup und unsere Stile bereit haben, können wir mit der Entwicklung der benötigten Funktionen für unsere Svelte-To-Do-Liste-App beginnen. In diesem Artikel verwenden wir Variablen und Props, um unsere App dynamisch zu gestalten, damit wir To-Dos hinzufügen und löschen, sie als erledigt markieren und nach Status filtern können.
Voraussetzungen: |
Es wird empfohlen, dass Sie mit den Kernsprachen HTML, CSS und JavaScript vertraut sind und Kenntnisse über die Terminal/Command Line besitzen. Sie benötigen ein Terminal mit installiertem Node und npm, um Ihre App zu kompilieren und zu erstellen. |
---|---|
Ziel: | Lernen und Anwenden von grundlegenden Svelte-Konzepten wie das Erstellen von Komponenten, das Übergeben von Daten mit Props, das Rendern von JavaScript-Ausdrücken in unserem Markup, das Ändern des Komponentenstatus und das Iterieren über Listen. |
Code mit uns
Git
Klonen Sie das GitHub-Repo (falls Sie dies noch nicht getan haben) mit:
git clone https://github.com/opensas/mdn-svelte-tutorial.git
Um dann zum aktuellen App-Status zu gelangen, führen Sie aus:
cd mdn-svelte-tutorial/03-adding-dynamic-behavior
Oder laden Sie direkt den Inhalt des Ordners herunter:
npx degit opensas/mdn-svelte-tutorial/03-adding-dynamic-behavior
Denken Sie daran, npm install && npm run dev
auszuführen, um Ihre App im Entwicklungsmodus zu starten.
REPL
Um mit uns über den REPL zu programmieren, beginnen Sie bei
https://svelte.dev/repl/c862d964d48d473ca63ab91709a0a5a0?version=3.23.2
Arbeiten mit To-Dos
Unsere Todos.svelte
-Komponente zeigt derzeit nur statisches Markup an; wir beginnen, es etwas dynamischer zu gestalten. Wir nehmen die Aufgabeninformationen aus dem Markup und speichern sie in einem todos
-Array. Außerdem erstellen wir zwei Variablen, um die Gesamtzahl der Aufgaben und die erledigten Aufgaben zu verfolgen.
Der Zustand unserer Komponente wird durch diese drei obersten Variablen dargestellt.
-
Erstellen Sie einen
<script>
-Abschnitt oben insrc/components/Todos.svelte
und fügen Sie ihm folgenden Inhalt hinzu:svelte<script> let todos = [ { id: 1, name: "Create a Svelte starter app", completed: true }, { id: 2, name: "Create your first component", completed: true }, { id: 3, name: "Complete the rest of the tutorial", completed: false } ]; let totalTodos = todos.length; let completedTodos = todos.filter((todo) => todo.completed).length; </script>
Nun machen wir etwas mit diesen Informationen.
-
Beginnen wir damit, eine Statusmeldung anzuzeigen. Suchen Sie die
<h2>
-Überschrift mit einerid
vonlist-heading
und ersetzen Sie die fest codierte Anzahl aktiver und abgeschlossener Aufgaben durch dynamische Ausdrücke:svelte<h2 id="list-heading">{completedTodos} out of {totalTodos} items completed</h2>
-
Gehen Sie zur App, und Sie sollten die Nachricht "2 von 3 Elementen erledigt" wie zuvor sehen, aber diesmal stammen die Informationen aus dem
todos
-Array. -
Um dies zu beweisen, gehen Sie zu diesem Array und versuchen Sie, einige der abgeschlossenen Eigenschaftenwerte des To-Do-Objekts zu ändern, und fügen Sie sogar ein neues To-Do-Objekt hinzu. Beobachten Sie, wie sich die Zahlen in der Nachricht entsprechend aktualisieren.
Dynamische Generierung der To-Dos aus den Daten
Derzeit sind unsere angezeigten To-Do-Elemente alle statisch. Wir möchten jedes Element in unserem todos
-Array durchlaufen und das Markup für jede Aufgabe rendern. Lassen Sie es uns jetzt tun.
HTML hat keine Möglichkeit, Logik wie Bedingungen und Schleifen auszudrücken. Svelte schon. In diesem Fall verwenden wir die {#each}
-Direktive, um das todos
-Array zu durchlaufen. Der zweite Parameter wird, falls angegeben, den Index des aktuellen Elements enthalten. Außerdem kann ein Schlüsselausdruck angegeben werden, der jedes Element eindeutig identifiziert. Svelte verwendet diesen, um die Liste zu differenzieren, wenn sich die Daten ändern, anstatt Elemente am Ende hinzuzufügen oder zu entfernen, und es ist eine gute Praxis, immer einen anzugeben. Schließlich kann ein :else
-Block bereitgestellt werden, der gerendert wird, wenn die Liste leer ist.
Probieren wir es aus.
-
Ersetzen Sie das vorhandene
<ul>
-Element durch die folgende vereinfachte Version, um eine Vorstellung davon zu bekommen, wie es funktioniert:svelte<ul> {#each todos as todo, index (todo.id)} <li> <input type="checkbox" checked={todo.completed}/> {index}. {todo.name} (id: {todo.id}) </li> {:else} Nothing to do here! {/each} </ul>
-
Gehen Sie zurück zur App; Sie sehen etwas wie dies:
-
Jetzt, da wir gesehen haben, dass dies funktioniert, generieren wir ein vollständiges To-Do-Element mit jeder Schleife der
{#each}
-Direktive und betten darin die Informationen aus demtodos
-Array ein:id
,name
undcompleted
. Ersetzen Sie Ihren vorhandenen<ul>
-Block wie folgt:svelte<!-- To-dos --> <ul role="list" class="todo-list stack-large" aria-labelledby="list-heading"> {#each todos as todo (todo.id)} <li class="todo"> <div class="stack-small"> <div class="c-cb"> <input type="checkbox" id="todo-{todo.id}" checked={todo.completed} /> <label for="todo-{todo.id}" class="todo-label"> {todo.name} </label> </div> <div class="btn-group"> <button type="button" class="btn"> Edit <span class="visually-hidden">{todo.name}</span> </button> <button type="button" class="btn btn__danger"> Delete <span class="visually-hidden">{todo.name}</span> </button> </div> </div> </li> {:else} <li>Nothing to do here!</li> {/each} </ul>
Beachten Sie, wie wir geschweifte Klammern verwenden, um JavaScript-Ausdrücke in HTML-Attribute einzubetten, so wie wir es mit den Attributen
checked
undid
des Kontrollkästchens gemacht haben.
Wir haben unser statisches Markup in eine dynamische Vorlage umgewandelt, die bereit ist, die Aufgaben aus dem Zustand unserer Komponente anzuzeigen. Großartig! Wir kommen der Sache näher.
Arbeiten mit Props
Mit einer fest codierten Liste von To-Dos ist unsere Todos
-Komponente nicht sehr nützlich. Um unsere Komponente in einen Allgemeinzweck-To-Do-Editor zu verwandeln, sollten wir es dem Elternelement dieser Komponente ermöglichen, die Liste der zu bearbeitenden To-Dos zu übergeben. Dadurch könnten wir sie in einem Webdienst oder im lokalen Speicher speichern und später zur Aktualisierung abrufen. Lassen Sie uns das Array also in ein prop
umwandeln.
-
Ersetzen Sie in
Todos.svelte
den vorhandenenlet todos = …
-Block durchexport let todos = []
.jsexport let todos = [];
Das mag sich anfangs etwas seltsam anfühlen. So funktioniert
export
normalerweise nicht in JavaScript-Modulen! So 'erweitert' Svelte JavaScript, indem es die gültige Syntax aufnimmt und ihr einen neuen Zweck gibt. In diesem Fall verwendet Svelte das Schlüsselwortexport
, um eine Variablendeklaration als Eigenschaft oder Prop zu markieren, was bedeutet, dass sie für Verbraucher der Komponente zugänglich wird.Sie können auch einen Standard-Anfangswert für ein Prop angeben. Dieser wird verwendet, wenn der Verbraucher der Komponente das Prop bei der Instanziierung der Komponente nicht angibt – oder wenn sein Anfangswert undefiniert ist.
Mit
export let todos = []
sagen wir Svelte, dass unsereTodos.svelte
-Komponente eintodos
-Attribut akzeptiert, das – wenn es weggelassen wird – auf ein leeres Array initialisiert wird. -
Schauen Sie sich die App an, und Sie sehen die Meldung "Nichts zu tun hier!". Das liegt daran, dass wir ihm momentan keinen Wert aus
App.svelte
übergeben, sodass der Standardwert verwendet wird. -
Verschieben wir nun unsere To-Dos nach
App.svelte
und übergeben sie als Prop an dieTodos.svelte
-Komponente. Aktualisieren Siesrc/App.svelte
wie folgt:svelte<script> import Todos from "./components/Todos.svelte"; let todos = [ { id: 1, name: "Create a Svelte starter app", completed: true }, { id: 2, name: "Create your first component", completed: true }, { id: 3, name: "Complete the rest of the tutorial", completed: false } ]; </script> <Todos todos={todos} />
-
Wenn der Attributname und der Variablenname übereinstimmen, erlaubt Svelte, die Variable als praktische Abkürzung einzutragen, sodass wir unsere letzte Zeile wie folgt umschreiben können. Probieren Sie dies jetzt aus.
svelte<Todos {todos} />
An diesem Punkt sollten Ihre To-Dos ebenso gerendert werden wie zuvor, außer dass wir sie jetzt von der App.svelte
-Komponente übergeben.
Umschalten und Entfernen von To-Dos
Fügen wir etwas Funktionalität hinzu, um den Aufgabenstatus umzuschalten. Svelte hat die on:eventname
-Direktive, um DOM-Ereignissen zu lauschen. Fügen wir einen Handler zum on:click
-Ereignis des Checkbox-Eingabes hinzu, um den abgeschlossenen Wert umzuschalten.
-
Aktualisieren Sie das
<input type="checkbox">
-Element insrc/components/Todos.svelte
wie folgt:svelte<input type="checkbox" id="todo-{todo.id}" on:click={() => todo.completed = !todo.completed} checked={todo.completed} />
-
Als Nächstes fügen wir eine Funktion hinzu, um ein To-Do aus unserem
todos
-Array zu entfernen. Am Ende des<script>
-Abschnitts vonTodos.svelte
, fügen Sie dieremoveTodo()
-Funktion wie folgt hinzu:jsfunction removeTodo(todo) { todos = todos.filter((t) => t.id !== todo.id); }
-
Wir rufen sie über den Löschen-Button auf. Aktualisieren Sie ihn mit einem
click
-Event wie folgt:svelte<button type="button" class="btn btn__danger" on:click={() => removeTodo(todo)} > Delete <span class="visually-hidden">{todo.name}</span> </button>
Ein sehr häufiger Fehler bei Handlern in Svelte ist es, das Ergebnis der Ausführung einer Funktion als Handler zu übergeben, anstatt die Funktion zu übergeben. Zum Beispiel, wenn Sie
on:click={removeTodo(todo)}}
angeben, wirdremoveTodo(todo)
ausgeführt und das Ergebnis wird als Handler übergeben, was nicht das ist, was wir im Sinn hatten.In diesem Fall müssen Sie
on:click={() => removeTodo(todo)}}
als Handler angeben. WennremoveTodo()
keine Parameter empfängt, könnten Sieon:event={removeTodo}
verwenden, aber nichton:event={removeTodo()}}
. Dies ist keine spezielle Svelte-Syntax – hier verwenden wir einfach reguläre JavaScript-Arrow-Funktionen.
Gut, das ist guter Fortschritt — an diesem Punkt können wir jetzt Aufgaben löschen. Wenn die Löschen-Schaltfläche eines To-Do-Elements gedrückt wird, wird das entsprechende To-Do aus dem todos
-Array entfernt, und die UI wird aktualisiert, um es nicht mehr anzuzeigen. Zudem können wir jetzt die Checkboxen markieren, und der abgeschlossene Status der relevanten To-Dos wird nun im todos
-Array aktualisiert.
Das "x von y Elementen erledigt"-Überschrift wird allerdings nicht aktualisiert. Lesen Sie weiter, um herauszufinden, warum dies passiert und wie wir es lösen können.
Reaktive To-Dos
Wie wir bereits gesehen haben, weiß Svelte jedes Mal, wenn der Wert einer obersten Variablen einer Komponente geändert wird, wie die UI aktualisiert werden muss. In unserer App wird der Wert des todos
-Arrays direkt jedes Mal aktualisiert, wenn ein To-Do umgeschaltet oder gelöscht wird, und so aktualisiert Svelte automatisch das DOM.
Dasselbe gilt jedoch nicht für totalTodos
und completedTodos
. Im nächsten Code, der ihnen beim Instanziieren der Komponente und Ausführen des Skripts zugewiesen wird, werden ihre Werte nicht geändert:
let totalTodos = todos.length;
let completedTodos = todos.filter((todo) => todo.completed).length;
Wir könnten sie nach Umschaltung und Entfernung der To-Dos neu berechnen, aber es gibt einen einfacheren Weg, es zu tun.
Wir können Svelte mitteilen, dass wir unsere totalTodos
- und completedTodos
-Variablen reaktiv gestalten möchten, indem wir sie mit $:
voranstellen. Svelte generiert den Code, um sie automatisch zu aktualisieren, wenn sich die Daten, von denen sie abhängen, ändern.
Hinweis:
Svelte verwendet die $:
JavaScript-Label-Statement-Syntax, um reaktive Anweisungen zu markieren. Ähnlich wie das Schlüsselwort export
, das zur Deklaration von Props verwendet wird, mag dies etwas fremdartig aussehen. Dies ist ein weiteres Beispiel dafür, wie Svelte gültige JavaScript-Syntax nutzt und ihr einen neuen Zweck verleiht – in diesem Fall bedeutet es "Führen Sie diesen Code erneut aus, wenn sich einer der referenzierten Werte ändert". Sobald Sie sich daran gewöhnt haben, werden Sie es nicht mehr missen wollen.
Aktualisieren Sie Ihre totalTodos
- und completedTodos
-Variablendefinitionen in src/components/Todos.svelte
wie folgt:
$: totalTodos = todos.length;
$: completedTodos = todos.filter((todo) => todo.completed).length;
Wenn Sie jetzt Ihre App überprüfen, sehen Sie, dass die Zahlen in der Überschrift aktualisiert werden, wenn To-Dos abgeschlossen oder gelöscht werden. Schön!
Hinter den Kulissen wird der Svelte-Compiler unseren Code analysieren und einen Abhängigkeitsbaum erstellen, und dann den JavaScript-Code generieren, um jede reaktive Anweisung neu zu bewerten, wenn eine ihrer Abhängigkeiten aktualisiert wird. Reaktivität in Svelte wird auf eine sehr leichte und performante Weise implementiert, ohne Zuhörer, Setter, Getter oder andere komplexe Mechanismen zu verwenden.
Neue To-Dos hinzufügen
Nun zum nächsten großen Abschnitt dieses Artikels — wir fügen Funktionalitäten hinzu, um neue To-Dos hinzuzufügen.
-
Zuerst erstellen wir eine Variable, um den Text des neuen To-Dos zu halten. Fügen Sie diese Deklaration dem
<script>
-Abschnitt vonTodos.svelte
hinzu:jslet newTodoName = "";
-
Nun werden wir diesen Wert im
<input>
für das Hinzufügen neuer Aufgaben verwenden. Dazu müssen wir unserenewTodoName
-Variable an dietodo-0
Eingabe binden, sodass der Wert dernewTodoName
-Variable synchron mit demvalue
-Eigenschaft des Eingabefeldes bleibt. Wir könnten etwas wie dies tun:svelte<input value={newTodoName} on:keydown={(e) => newTodoName = e.target.value} />
Wann immer sich der Wert der Variablen
newTodoName
ändert, wird er imvalue
-Attribut des Eingabefeldes reflektiert, und wann immer eine Taste im Eingabefeld gedrückt wird, aktualisieren wir den Inhalt der VariablennewTodoName
.Dies ist eine manuelle Implementierung der Zwei-Wege-Datenbindung für ein Eingabefeld. Aber wir müssen dies nicht tun — Svelte bietet eine einfachere Möglichkeit, jede Eigenschaft mit einer Variablen zu binden, mit der
bind:property
-Direktive:svelte<input bind:value={newTodoName} />
Also, lassen Sie uns dies implementieren. Aktualisieren Sie die
todo-0
Eingabe wie folgt:svelte<input bind:value={newTodoName} type="text" id="todo-0" autocomplete="off" class="input input__lg" />
-
Eine einfache Möglichkeit, zu testen, ob dies funktioniert, besteht darin, eine reaktive Anweisung hinzuzufügen, um den Inhalt von
newTodoName
zu protokollieren. Fügen Sie diesen Code am Ende des<script>
-Abschnitts hinzu:js$: console.log("newTodoName: ", newTodoName);
Hinweis: Wie Sie vielleicht bemerkt haben, sind reaktive Anweisungen nicht auf Variablendeklarationen beschränkt. Sie können jede JavaScript-Anweisung nach dem
$:
-Zeichen setzen. -
Versuchen Sie jetzt, mit
localhost:5042
wieder zu laden, Strg + Umschalt + K zu drücken, um Ihre Browserkonsole zu öffnen, und etwas in das Eingabefeld einzugeben. Sie sollten Ihre Einträge protokolliert sehen. Zu diesem Zeitpunkt können Sie das reaktiveconsole.log()
löschen, wenn Sie möchten. -
Als nächstes erstellen wir eine Funktion, um das neue To-Do hinzuzufügen —
addTodo()
—, welche ein neuestodo
-Objekt zumtodos
-Array hinzufügt. Fügen Sie diese am Ende Ihres<script>
-Blocks insrc/components/Todos.svelte
hinzu:jsfunction addTodo() { todos.push({ id: 999, name: newTodoName, completed: false }); newTodoName = ""; }
Hinweis: Zurzeit weisen wir jedem To-Do nur die gleiche
id
zu, aber keine Sorge, wir werden das gleich beheben. -
Nun wollen wir unser HTML aktualisieren, damit wir
addTodo()
ausführen, wann immer das Formular abgeschickt wird. Aktualisieren Sie das NewTodo-Formular-Öffnungstag wie folgt:svelte<form on:submit|preventDefault={addTodo}>
Die
on:eventname
-Direktive unterstützt das Hinzufügen von Modifikatoren zum DOM-Ereignis mit dem|
-Zeichen. In diesem Fall teilt der ModifierpreventDefault
Svelte mit, den Code zu generieren, umevent.preventDefault()
vor dem Ausführen des Handlers aufzurufen. Erkunden Sie den vorherigen Link, um zu sehen, welche anderen Modifikatoren verfügbar sind. -
Wenn Sie versuchen, zu diesem Zeitpunkt neue To-Dos hinzuzufügen, werden die neuen To-Dos zum
todos
-Array hinzugefügt, aber unsere UI aktualisiert sich nicht. Denken Sie daran, dass in Svelte Reaktivität durch Zuweisungen ausgelöst wird. Das bedeutet, dass dieaddTodo()
-Funktion ausgeführt wird, das Element demtodos
-Array hinzugefügt wird, aber Svelte das nicht als Modifikation erkennt und die Task-<ul>
daher nicht aktualisiert.Das Hinzufügen von
todos = todos
am Ende deraddTodo()
-Funktion würde das Problem lösen, aber es erscheint seltsam, dies am Ende der Funktion aufzunehmen. Stattdessen nehmen wir diepush()
-Methode heraus und verwenden Spread-Syntax, um dasselbe Ergebnis zu erzielen: wir weisen demtodos
-Array einen Wert zu, der demtodos
-Array plus dem neuen Objekt entspricht.Hinweis:
Array
hat mehrere veränderliche Operationen:push()
,pop()
,splice()
,shift()
,unshift()
,reverse()
undsort()
. Diese zu verwenden, führt oft zu Seiteneffekten und schwer nachvollziehbaren Fehlern. Indem wir die Spread-Syntax anstelle vonpush()
verwenden, vermeiden wir das mutierende Array, was als gute Praxis angesehen wird.Aktualisieren Sie Ihre
addTodo()
-Funktion wie folgt:jsfunction addTodo() { todos = [...todos, { id: 999, name: newTodoName, completed: false }]; newTodoName = ""; }
Jedem To-Do eine eindeutige ID geben
Wenn Sie jetzt versuchen, neue To-Dos in Ihrer App hinzuzufügen, können Sie ein neues To-Do hinzufügen und es in der UI erscheinen lassen — einmal. Wenn Sie es ein zweites Mal versuchen, wird es nicht funktionieren, und Sie erhalten eine Konsolenmeldung, die besagt "Fehler: Doppelte Schlüssel in einem gekeyten Each sind nicht erlaubt". Wir benötigen eindeutige IDs für unsere To-Dos.
-
Erklären wir eine
newTodoId
-Variable, die aus der Anzahl der To-Dos plus 1 berechnet wird, und machen wir sie reaktiv. Fügen Sie folgendes Snippet zum<script>
-Abschnitt hinzu:jslet newTodoId; $: { if (totalTodos === 0) { newTodoId = 1; } else { newTodoId = Math.max(...todos.map((t) => t.id)) + 1; } }
Hinweis: Wie Sie sehen können, sind reaktive Anweisungen nicht auf Einzeiler beschränkt. Das Folgende würde auch funktionieren, ist aber etwas weniger lesbar:
$: newTodoId = totalTodos ? Math.max(...todos.map((t) => t.id)) + 1 : 1
-
Wie erreicht Svelte dies? Der Compiler analysiert den gesamten reaktiven Ausdruck und erkennt, dass er von der
totalTodos
Variablen und demtodos
Array abhängt. Sobald sich eine von ihnen ändert, wird dieser Code neu bewertet undnewTodoId
entsprechend aktualisiert.Lassen Sie uns dies in unserer
addTodo()
-Funktion verwenden. Aktualisieren Sie es wie folgt:jsfunction addTodo() { todos = [...todos, { id: newTodoId, name: newTodoName, completed: false }]; newTodoName = ""; }
Filtern von To-Dos nach Status
Schließlich in diesem Artikel werden wir die Fähigkeit implementieren, unsere To-Dos nach Status zu filtern. Wir erstellen eine Variable, um den aktuellen Filter zu halten, und eine Hilfsfunktion, die die gefilterten To-Dos zurückgibt.
-
Fügen Sie am Ende unseres
<script>
-Abschnitts folgendes hinzu:jslet filter = "all"; const filterTodos = (filter, todos) => filter === "active" ? todos.filter((t) => !t.completed) : filter === "completed" ? todos.filter((t) => t.completed) : todos;
Wir verwenden die
filter
-Variable, um den aktiven Filter zu steuern: alle, aktiv oder abgeschlossen. Das Zuweisen eines dieser Werte zur Filtervariablen aktiviert den Filter und aktualisiert die Liste der To-Dos entsprechend. Lassen Sie uns sehen, wie das erreicht werden kann.Die
filterTodos()
-Funktion wird den aktuellen Filter und die Liste der To-Dos entgegennehmen und ein neues Array von gefilterten To-Dos zurückgeben. -
Aktualisieren wir das Filter-Button-Markup, um es dynamisch zu machen, und aktualisieren wir den aktuellen Filter, wenn der Benutzer einen der Filter-Buttons drückt. Aktualisieren Sie es wie folgt:
svelte<div class="filters btn-group stack-exception"> <button class="btn toggle-btn" class:btn__primary={filter === 'all'} aria-pressed={filter === 'all'} on:click={() => filter = 'all'} > <span class="visually-hidden">Show</span> <span>All</span> <span class="visually-hidden">tasks</span> </button> <button class="btn toggle-btn" class:btn__primary={filter === 'active'} aria-pressed={filter === 'active'} on:click={() => filter = 'active'} > <span class="visually-hidden">Show</span> <span>Active</span> <span class="visually-hidden">tasks</span> </button> <button class="btn toggle-btn" class:btn__primary={filter === 'completed'} aria-pressed={filter === 'completed'} on:click={() => filter = 'completed'} > <span class="visually-hidden">Show</span> <span>Completed</span> <span class="visually-hidden">tasks</span> </button> </div>
In diesem Markup passieren einige Dinge.
Wir zeigen den aktuellen Filter an, indem wir die
btn__primary
-Klasse auf den aktiven Filter-Button anwenden. Um Stilklassen bedingt auf ein Element anzuwenden, verwenden wir dieclass:name={value}
-Direktive. Wenn der Wert-Ausdruck zu einem wahrheitsgemäßen Wert ausgewertet wird, wird der Klassenname angewendet. Sie können viele dieser Direktiven mit verschiedenen Bedingungen zu einem Element hinzufügen. Also wenn wirclass:btn__primary={filter === 'all'}
ausgeben, wird Svelte diebtn__primary
-Klasse anwenden, wenn filter gleich alle ist.Hinweis: Svelte bietet eine Abkürzung, die es erlaubt,
<div class:active={active}>
auf<div class:active>
zu verkürzen, wenn die Klasse mit dem Variablennamen übereinstimmt.Etwas Ähnliches passiert bei
aria-pressed={filter === 'all'}
: Wenn der zwischen geschweiften Klammern eingefügte JavaScript-Ausdruck zu einem wahrheitsgemäßen Wert ausgewertet wird, wird dasaria-pressed
-Attribut auf den Button angewendet.Wann immer wir auf einen Button klicken, aktualisieren wir die Filter-Variable, indem wir
on:click={() => filter = 'all'}
ausgeben. Lesen Sie weiter, um herauszufinden, wie Svelte-Reaktivität den Rest erledigen wird. -
Jetzt müssen wir nur noch die Hilfsfunktion in die
{#each}
-Schleife einfügen; aktualisieren Sie sie wie folgt:svelte… <ul role="list" class="todo-list stack-large" aria-labelledby="list-heading"> {#each filterTodos(filter, todos) as todo (todo.id)} …
Nach Analyse unseres Codes erkennt Svelte, dass unsere
filterTodos()
-Funktion von den Variablenfilter
undtodos
abhängt. Und wie bei allen anderen dynamischen Ausdrücken, die im Markup eingebettet sind, wird jedesmal, wenn eine dieser Abhängigkeiten verändert wird, das DOM entsprechend aktualisiert. Also wird jedes Mal, wenn sichfilter
odertodos
ändert, diefilterTodos()
-Funktion neu bewertet und die Elemente in der Schleife werden aktualisiert.
Hinweis:
Reaktivität kann manchmal knifflig sein. Svelte erkennt filter
als Abhängigkeit, weil wir es im filterTodos(filter, todo)
Ausdruck referenzieren. filter
ist eine oberste Variable, sodass wir versucht sein könnten, sie von den Hilfsfunktionen-Parametern zu entfernen und sie einfach so aufzurufen: filterTodos(todo)
. Das würde funktionieren, aber jetzt hat Svelte keine Möglichkeit herauszufinden, dass {#each filterTodos(todos)}}
von filter
abhängt, und die Liste der gefilterten To-Dos wird nicht aktualisiert, wenn sich der Filter ändert. Denken Sie immer daran, dass Svelte unseren Code analysiert, um Abhängigkeiten herauszufinden; daher ist es besser, explizit darüber zu sein und nicht auf die Sichtbarkeit der obersten Variablen zu vertrauen. Außerdem ist es eine gute Praxis, unseren Code klar und explizit darüber zu machen, welche Informationen er verwendet.
Der Code bisher
Git
Um den Stand des Codes zu sehen, wie er am Ende dieses Artikels sein sollte, greifen Sie auf Ihre Kopie unseres Repos wie folgt zu:
cd mdn-svelte-tutorial/04-componentizing-our-app
Oder laden Sie direkt den Inhalt des Ordners herunter:
npx degit opensas/mdn-svelte-tutorial/04-componentizing-our-app
Denken Sie daran, npm install && npm run dev
auszuführen, um Ihre App im Entwicklungsmodus zu starten.
REPL
Um den aktuellen Stand des Codes in einem REPL zu sehen, besuchen Sie:
https://svelte.dev/repl/99b9eb228b404a2f8c8959b22c0a40d3?version=3.23.2
Zusammenfassung
Das ist es erst einmal! In diesem Artikel haben wir bereits die meiste gewünschte Funktionalität implementiert. Unsere App kann To-Dos anzeigen, hinzufügen und löschen, deren abgeschlossenen Status umschalten, zeigen, wie viele von ihnen erledigt sind, und Filter anwenden.
Kurz zusammengefasst, haben wir die folgenden Themen behandelt:
- Erstellen und Verwenden von Komponenten
- Umwandeln von statischem Markup in eine lebendige Vorlage
- Einbetten von JavaScript-Ausdrücken in unser Markup
- Iterieren über Listen mit der
{#each}
-Direktive - Übergeben von Informationen zwischen Komponenten mit Props
- Lauschen auf DOM-Ereignisse
- Deklarieren reaktiver Anweisungen
- Grundlegendes Debugging mit
console.log()
und reaktiven Anweisungen - Binden von HTML-Eigenschaften mit der
bind:property
-Direktive - Auslösen von Reaktivität mit Zuweisungen
- Verwenden von reaktiven Ausdrücken zur Datenfilterung
- Explizites Definieren unserer reaktiven Abhängigkeiten
Im nächsten Artikel werden wir weitere Funktionalitäten hinzufügen, die es Benutzern ermöglichen, To-Dos zu bearbeiten.