Dynamisches Verhalten in Svelte: Arbeiten mit Variablen und Props
Da wir nun unser Markup und unsere Styles vorbereitet haben, können wir mit der Entwicklung der erforderlichen Funktionen für unsere Svelte-zu-erledigen-Liste-App beginnen. In diesem Artikel werden wir Variablen und Props verwenden, um unsere App dynamisch zu gestalten, damit wir Aufgaben hinzufügen und löschen, als erledigt markieren und nach Status filtern können.
Voraussetzungen: |
Es wird mindestens empfohlen, dass Sie mit den Kernsprachen HTML, CSS und JavaScript vertraut sind und über Kenntnisse der Terminal-/Kommandozeile verfügen. Sie benötigen ein Terminal mit installiertem Node und npm, um Ihre App zu kompilieren und zu bauen. |
---|---|
Ziel: | Erlernen und Anwenden einiger grundlegender Svelte-Konzepte, wie das Erstellen von Komponenten, Übergeben von Daten mit Props, Rendern von JavaScript-Ausdrücken in unserem Markup, Ändern des Komponentenstatus und Iterieren über Listen. |
Coden Sie mit uns mit
Git
Klonen Sie das GitHub-Repository (falls Sie dies noch nicht getan haben) mit:
git clone https://github.com/opensas/mdn-svelte-tutorial.git
Um zum aktuellen Status der App zu gelangen, führen Sie Folgendes 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
Vergessen Sie nicht, npm install && npm run dev
auszuführen, um Ihre App im Entwicklungsmodus zu starten.
REPL
Um mit uns mithilfe des REPL zu coden, beginnen Sie hier:
https://svelte.dev/repl/c862d964d48d473ca63ab91709a0a5a0?version=3.23.2
Arbeiten mit Aufgaben
Unsere Todos.svelte
-Komponente zeigt derzeit nur statisches Markup an; lassen Sie uns damit beginnen, es etwas dynamischer zu gestalten. Wir werden die Aufgabeninformationen aus dem Markup nehmen und in einem todos
-Array speichern. Wir erstellen auch zwei Variablen, um die Gesamtanzahl der Aufgaben und der erledigten Aufgaben nachzuverfolgen.
Der Status unserer Komponente wird durch diese drei obersten Variablen repräsentiert.
-
Erstellen Sie einen
<script>
-Abschnitt am Anfang vonsrc/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 wollen wir etwas mit diesen Informationen machen.
-
Lassen Sie uns mit der Anzeige einer Statusnachricht beginnen. Suchen Sie die
<h2>
-Überschrift mit einerid
vonlist-heading
und ersetzen Sie die festkodierte Anzahl der aktiven und abgeschlossenen 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 Aufgaben abgeschlossen" wie zuvor sehen, aber diesmal kommen die Informationen aus dem
todos
-Array. -
Um dies zu beweisen, gehen Sie zu diesem Array und versuchen Sie, einige der
completed
-Eigenschaftswerte der Aufgabenobjekte zu ändern, und fügen Sie sogar ein neues Aufgabenobjekt hinzu. Beobachten Sie, wie die Zahlen in der Nachricht angemessen aktualisiert werden.
Dynamische Generierung der Aufgaben aus den Daten
Im Moment sind unsere angezeigten Aufgaben alle statisch. Wir möchten über jedes Element in unserem todos
-Array iterieren und das Markup für jede Aufgabe rendern, also tun wir das jetzt.
HTML hat keine Möglichkeit, Logik auszudrücken — wie Bedingungen und Schleifen. Svelte kann das. In diesem Fall verwenden wir die {#each}
-Direktive, um über das todos
-Array zu iterieren. Der zweite Parameter, falls vorhanden, enthält den Index des aktuellen Elements. Außerdem kann ein Schlüssel-Ausdruck bereitgestellt werden, der jedes Element eindeutig identifiziert. Svelte verwendet ihn, um die Liste zu differenzieren, wenn sich die Daten ändern, anstatt Elemente am Ende hinzuzufügen oder zu entfernen. Es ist eine gute Praxis, immer einen anzugeben. Schließlich kann ein :else
-Block bereitgestellt werden, der gerendert wird, wenn die Liste leer ist.
Lassen Sie uns dies ausprobieren.
-
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 werden etwas sehen wie:
-
Jetzt, da wir gesehen haben, dass dies funktioniert, lassen Sie uns ein vollständiges Aufgaben-Element mit jeder Schleife der
{#each}
-Direktive generieren und darin die Informationen aus demtodos
-Array einbetten:id
,name
undcompleted
. Ersetzen Sie Ihren vorhandenen<ul>
-Block durch Folgendes: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, wie wir es mit den Attributen
checked
undid
des Kontrollkästchens gemacht haben.
Wir haben unser statisches Markup in eine dynamische Vorlage verwandelt, die bereit ist, die Aufgaben aus dem Status unserer Komponente anzuzeigen. Großartig! Wir nähern uns unserem Ziel.
Arbeiten mit Props
Mit einer festkodierten Liste von Aufgaben ist unsere Todos
-Komponente nicht sehr nützlich. Um unsere Komponente in einen allgemeinen Aufgaben-Editor zu verwandeln, sollten wir es dem übergeordneten Element dieser Komponente ermöglichen, die Liste der zu bearbeitenden Aufgaben zu übergeben. Auf diese Weise könnten wir sie in einem Webdienst oder lokalem Speicher speichern und später abrufen, um sie zu aktualisieren. Lassen Sie uns das Array in ein prop
verwandeln.
-
Ersetzen Sie in
Todos.svelte
den vorhandenenlet todos = …
-Block durchexport let todos = []
.jsexport let todos = [];
Dies mag zunächst etwas merkwürdig erscheinen. So funktioniert
export
normalerweise nicht in JavaScript-Modulen! Auf diese Weise "erweitert" Svelte JavaScript, indem es gültige Syntax nimmt und ihr einen neuen Zweck gibt. In diesem Fall verwendet Svelte dasexport
-Schlüsselwort, um eine Variablendeklaration als Eigenschaft oder Prop zu kennzeichnen, was bedeutet, dass sie den Verbrauchern der Komponente zugänglich wird.Sie können auch einen Standard-Startwert 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 Startwert undefiniert ist.
Also sagen wir mit
export let todos = []
Svelte, dass unsereTodos.svelte
-Komponente eintodos
-Attribut akzeptieren wird, das, wenn es weggelassen wird, auf ein leeres Array initialisiert wird. -
Schauen Sie sich die App an, und Sie werden die Nachricht "Nichts zu tun hier!" sehen. Dies liegt daran, dass wir derzeit keinen Wert von
App.svelte
an sie übergeben, sodass der Standardwert verwendet wird. -
Lassen Sie uns nun unsere Aufgaben zu
App.svelte
verschieben und sie als Prop an dieTodos.svelte
-Komponente übergeben. 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 das Attribut und die Variable denselben Namen haben, erlaubt Svelte Ihnen, nur die Variable als praktischen Kurzweg anzugeben, sodass wir unsere letzte Zeile so umschreiben können. Probieren Sie dies jetzt aus.
svelte<Todos {todos} />
An diesem Punkt sollten Ihre Aufgaben genauso gerendert werden wie zuvor, außer dass wir sie jetzt aus der App.svelte
-Komponente übergeben.
Umschalten und Entfernen von Aufgaben
Lassen Sie uns etwas Funktionalität hinzufügen, um den Aufgabenstatus umzuschalten. Svelte hat die on:eventname
-Direktive zum Abhören von DOM-Ereignissen. Lassen Sie uns einen Handler für das on:click
-Ereignis des Checkbox-Inputs hinzufügen, 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 eine Aufgabe aus unserem
todos
-Array zu entfernen. Fügen Sie am Ende des<script>
-Abschnitts vonTodos.svelte
dieremoveTodo()
-Funktion wie folgt hinzu:jsfunction removeTodo(todo) { todos = todos.filter((t) => t.id !== todo.id); }
-
Wir rufen sie über die Löschen-Schaltfläche auf. Aktualisieren Sie sie mit einem
click
-Ereignis, 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 mit Handlers in Svelte besteht darin, 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 als Handler übergeben, was nicht unsere Absicht war.In diesem Fall müssen Sie
on:click={() => removeTodo(todo)}}
als Handler angeben. WennremoveTodo()
keine Parameter erhalten würde, könnten Sieon:event={removeTodo}
verwenden, aber nichton:event={removeTodo()}}
. Dies ist keine spezielle Svelte-Syntax – hier verwenden wir einfach reguläre JavaScript-Pfeilfunktionen.
Das ist wieder ein Fortschritt – an diesem Punkt können wir jetzt Aufgaben löschen. Wenn die Löschen-Schaltfläche eines Aufgabenpostens gedrückt wird, wird die betreffende Aufgabe aus dem todos
-Array entfernt und die Benutzeroberfläche so aktualisiert, dass sie nicht mehr angezeigt wird. Darüber hinaus können wir nun die Kontrollkästchen ankreuzen und der abgeschlossene Status der betreffenden Aufgaben im todos
-Array wird aktualisiert.
Allerdings wird die Überschrift "x von y Aufgaben abgeschlossen" nicht aktualisiert. Lesen Sie weiter, um herauszufinden, warum dies geschieht und wie wir es lösen können.
Reaktive Aufgaben
Wie wir bereits gesehen haben, weiß Svelte jedes Mal, wenn der Wert einer zuweisbaren Variablen auf Komponentenebene geändert wird, wie die Benutzeroberfläche aktualisiert werden sollte. In unserer App wird der Wert des todos
-Arrays jedes Mal direkt aktualisiert, wenn eine Aufgabe umgeschaltet oder gelöscht wird, sodass Svelte das DOM automatisch aktualisiert.
Dasselbe gilt jedoch nicht für totalTodos
und completedTodos
. In folgendem Code wird ihnen ein Wert zugewiesen, wenn die Komponente instanziiert wird und das Skript ausgeführt wird, danach werden ihre Werte jedoch nicht geändert:
let totalTodos = todos.length;
let completedTodos = todos.filter((todo) => todo.completed).length;
Wir könnten sie nach dem Umschalten und Entfernen von Aufgaben neu berechnen, aber es gibt einen einfacheren Weg, dies zu tun.
Wir können Svelte sagen, dass wir wollen, dass unsere totalTodos
- und completedTodos
-Variablen reaktiv sind, indem wir sie mit $:
voranstellen. Svelte generiert den Code, um sie automatisch zu aktualisieren, wann immer sich Daten ändern, auf die sie angewiesen sind.
Hinweis: Svelte verwendet die $:
JavaScript-Label-Anweisungssyntax, um reaktive Anweisungen zu markieren. Ähnlich wie das export
-Schlüsselwort, das für die Deklaration von Props verwendet wird, mag dies etwas fremd wirken. Dies ist ein weiteres Beispiel dafür, wie Svelte gültige JavaScript-Syntax nutzt und ihr einen neuen Zweck gibt – in diesem Fall bedeutet es "führe diesen Code erneut aus, wann immer einer der referenzierten Werte sich ändert". Sobald man sich daran gewöhnt hat, gibt es kein Zurück mehr.
Aktualisieren Sie die Definitionen Ihrer totalTodos
- und completedTodos
-Variablen in src/components/Todos.svelte
wie folgt:
$: totalTodos = todos.length;
$: completedTodos = todos.filter((todo) => todo.completed).length;
Wenn Sie Ihre App jetzt prüfen, sehen Sie, dass die Überschriftenzahlen aktualisiert werden, wenn Aufgaben abgeschlossen oder gelöscht werden. Gut gemacht!
Hinter den Kulissen wird der Svelte-Compiler unseren Code analysieren und ein Abhängigkeitsbaum erstellen; dann generiert er den JavaScript-Code, um jede reaktive Anweisung automatisch neu zu bewerten, wenn einer ihrer Abhängigkeiten aktualisiert wird. Die Reaktivität in Svelte wird auf eine sehr leichte und performante Weise implementiert, ohne Zuhörer, Setter, Getter oder andere komplexe Mechanismen zu verwenden.
Hinzufügen neuer Aufgaben
Nun zum nächsten wichtigen Punkt für diesen Artikel – fügen wir einige Funktionalität hinzu, um neue Aufgaben hinzuzufügen.
-
Zuerst erstellen wir eine Variable, um den Text der neuen Aufgabe zu halten. Fügen Sie diese Deklaration dem
<script>
-Abschnitt derTodos.svelte
-Datei hinzu:jslet newTodoName = "";
-
Jetzt verwenden wir diesen Wert im
<input>
zum Hinzufügen neuer Aufgaben. Dazu müssen wir unserenewTodoName
-Variable an dastodo-0
-Eingabefeld binden, sodass der Wert dernewTodoName
-Variable mit dervalue
-Eigenschaft des Eingabefelds synchronisiert bleibt. Wir könnten so etwas tun:svelte<input value={newTodoName} on:keydown={(e) => newTodoName = e.target.value} />
Jedes Mal, wenn sich der Wert der Variablen
newTodoName
ändert, wird er imvalue
-Attribut des Eingabefelds wiedergegeben, und jedes Mal, wenn 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 das nicht tun – Svelte bietet eine einfachere Methode, um jede Eigenschaft an eine Variable zu binden, indem die
bind:property
-Direktive verwendet wird:svelte<input bind:value={newTodoName} />
Lassen Sie uns dies implementieren. Aktualisieren Sie das
todo-0
-Eingabefeld wie folgt:svelte<input bind:value={newTodoName} type="text" id="todo-0" autocomplete="off" class="input input__lg" />
-
Eine einfache Möglichkeit, dies zu testen, 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, zu
localhost:5042
zurückzukehren, Strg + Shift + K zu drücken, um die Konsolenübersicht Ihres Browsers zu öffnen und etwas in das Eingabefeld einzugeben. Sie sollten Ihre Eingaben protokolliert sehen. An diesem Punkt können Sie das reaktiveconsole.log()
löschen, wenn Sie möchten. -
Als Nächstes erstellen wir eine Funktion, um die neue Aufgabe hinzuzufügen -
addTodo()
- die ein neuestodo
-Objekt demtodos
-Array hinzufügt. Fügen Sie dies am Ende Ihres<script>
-Blocks insrc/components/Todos.svelte
hinzu:jsfunction addTodo() { todos.push({ id: 999, name: newTodoName, completed: false }); newTodoName = ""; }
Hinweis: Im Moment weisen wir einfach jeder Aufgabe dieselbe
id
zu, aber keine Sorge, wir werden das bald beheben. -
Jetzt möchten wir unser HTML aktualisieren, damit
addTodo()
bei jeder Formulardiagnose aufgerufen wird. Aktualisieren Sie dasNewTodo
-Formular analog dem Starttag: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 sagt uns der ModifikatorpreventDefault
, dass Svelte den Code generieren soll, umevent.preventDefault()
vor der Ausführung des Handlers aufzurufen. Schauen Sie sich den vorherigen Link an, um zu sehen, welche anderen Modifikatoren verfügbar sind. -
Beim Versuch, neue Aufgaben hinzuzufügen, werden neue Aufgaben dem Aufgaben-Array hinzugefügt, aber unsere Benutzeroberfläche wird nicht aktualisiert. Erinnern Sie sich daran, dass in Svelte Reaktivität durch Zuweisungen ausgelöst wird. Das bedeutet, dass die Funktion
addTodo()
ausgeführt wird, das Element demtodos
-Array hinzugefügt wird, aber Svelte erkennt nicht, dass diepush
-Methode das Array geändert hat, also wird sie die Aufgaben-<ul>
nicht aktualisieren.Das Hinzufügen von
todos = todos
am Ende der FunktionaddTodo()
würde das Problem lösen, aber es scheint seltsam, dies am Ende der Funktion einfügen zu müssen. Stattdessen entfernen wir diepush()
-Methode und verwenden die Spread-Syntax, um dasselbe Ergebnis zu erzielen: Wir ordnen demtodos
-Array einen Wert zu, der gleich demtodos
-Array plus dem neuen Objekt ist.Hinweis:
Array
hat mehrere mutierende Operationen:push()
,pop()
,splice()
,shift()
,unshift()
,reverse()
undsort()
. Durch ihre Verwendung entstehen häufig Seiteneffekte und schwer zu verfolgende Fehler. Indem wir die Spread-Syntax anstelle vonpush()
verwenden, vermeiden wir die Veränderung des Arrays, was als gute Praxis angesehen wird.Aktualisieren Sie Ihre Funktion
addTodo()
wie folgt:jsfunction addTodo() { todos = [...todos, { id: 999, name: newTodoName, completed: false }]; newTodoName = ""; }
Jeder Aufgabe eine eindeutige ID geben
Wenn Sie jetzt in Ihrer App neue Aufgaben hinzufügen, können Sie eine neue Aufgabe hinzufügen und sie wird einmal in der Benutzeroberfläche angezeigt. Wenn Sie es ein zweites Mal versuchen, funktioniert es nicht, und Sie erhalten eine Konsolenmeldung mit "Error: Cannot have duplicate keys in a keyed each". Wir benötigen eindeutige IDs für unsere Aufgaben.
-
Lassen Sie uns eine
newTodoId
-Variable deklarieren, die aus der Anzahl der Aufgaben plus 1 berechnet und reaktiv gemacht wird. Fügen Sie den folgenden Code dem<script>
-Abschnitt hinzu:jslet newTodoId; $: { if (totalTodos === 0) { newTodoId = 1; } else { newTodoId = Math.max(...todos.map((t) => t.id)) + 1; } }
Hinweis: Wie Sie sehen, sind reaktive Anweisungen nicht auf Einzeiler beschränkt. Das Folgende würde auch funktionieren, ist jedoch etwas weniger lesbar:
$: newTodoId = totalTodos ? Math.max(...todos.map((t) => t.id)) + 1 : 1
-
Wie erreicht Svelte dies? Der Compiler analysiert die gesamte reaktive Anweisung und erkennt, dass sie von der Variablen
totalTodos
und demtodos
-Array abhängt. Jedes Mal, wenn einer von ihnen geändert wird, wird dieser Code neu ausgewertet undnewTodoId
entsprechend aktualisiert.Lassen Sie uns dies in unserer Funktion
addTodo()
verwenden. Aktualisieren Sie sie wie folgt:jsfunction addTodo() { todos = [...todos, { id: newTodoId, name: newTodoName, completed: false }]; newTodoName = ""; }
Filtern von Aufgaben nach Status
Zum Schluss für diesen Artikel implementieren wir die Möglichkeit, unsere Aufgaben nach Status zu filtern. Wir erstellen eine Variable, um den aktuellen Filter zu halten, und eine Hilfsfunktion, die die gefilterten Aufgaben zurückgibt.
-
Fügen Sie dem 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 Variable
filter
, um den aktiven Filter zu steuern: alle, aktiv oder abgeschlossen. Einfach einer dieser Werte der Filtervariablen zuweisen, aktiviert den Filter und aktualisiert die Liste der Aufgaben. Schauen wir uns an, wie das zu erreichen ist.Die Funktion
filterTodos()
erhält den aktuellen Filter und die Liste der Aufgaben und gibt ein neues Array von Aufgaben zurück, das entsprechend gefiltert ist. -
Lassen Sie uns das Filter-Schaltflächen-Markup so aktualisieren, dass es dynamisch wird und den aktuellen Filter aktualisiert, wenn der Benutzer eine der Filters-Schaltflächen drückt. Aktualisieren Sie es so:
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 ein paar Dinge.
Wir zeigen den aktuellen Filter an, indem wir die Klasse
btn__primary
auf die aktive Filter-Schaltfläche anwenden. Um bedingt Stilklassen auf ein Element anzuwenden, verwenden wir dieclass:name={value}
-Direktive. Wenn der Wertausdruck auf einen wahrheitswertigen Wert auswertet, wird der Klassenname angewendet. Sie können viele dieser Direktiven, mit verschiedenen Bedingungen, auf dasselbe Element anwenden. Wenn wir alsoclass:btn__primary={filter === 'all'}
ausgeben, wird Svelte die Klassebtn__primary
anwenden, wenn der Filter allen entspricht.Hinweis: Svelte bietet eine Abkürzung, die es uns ermöglicht,
<div class:active={active}>
zu<div class:active>
zu verkürzen, wenn die Klasse mit dem Variablennamen übereinstimmt.Ähnliches passiert mit
aria-pressed={filter === 'all'}
: Wenn der JavaScript-Ausdruck in geschweiften Klammern einen wahrheitswertigen Wert ergibt, wird dasaria-pressed
-Attribut dem Button zugefügt.Jedes Mal, wenn wir auf einen Button klicken, aktualisieren wir die Filter-Variable, indem wir
on:click={() => filter = 'all'}
ausgeben. Lesen Sie weiter, um zu erfahren, wie Svelte-Reaktivität den Rest übernehmen wird. -
Jetzt müssen wir nur noch die Hilfsfunktion in der
{#each}
-Schleife verwenden; aktualisieren Sie sie so:svelte… <ul role="list" class="todo-list stack-large" aria-labelledby="list-heading"> {#each filterTodos(filter, todos) as todo (todo.id)} …
Nach der Analyse unseres Codes erkennt Svelte, dass unsere Funktion
filterTodos()
von den Variablenfilter
undtodos
abhängt. Und, genau wie bei jedem anderen dynamischen Ausdruck, der im Markup eingebettet ist, wann immer eine dieser Abhängigkeiten sich ändert, wird das DOM entsprechend aktualisiert. Jedes Mal, wenn sichfilter
odertodos
ändert, wird die FunktionfilterTodos()
erneut ausgewertet und die Elemente innerhalb der Schleife werden aktualisiert.
Hinweis: Reaktivität kann manchmal schwierig sein. Svelte erkennt filter
als eine Abhängigkeit, weil wir es im filterTodos(filter, todos)
-Ausdruck referenzieren. filter
ist eine zuweisbare Variable auf Komponentenebene, daher könnten wir versucht sein, sie aus den Hilfsfunktionsparametern zu entfernen und sie einfach so aufzurufen: filterTodos(todos)
. Dies würde funktionieren, aber jetzt hat Svelte keine Möglichkeit herauszufinden, dass {#each filterTodos(todos) }
von filter
abhängt, und die Liste der gefilterten Aufgaben wird nicht aktualisiert, wenn sich der Filter ändert. Denken Sie immer daran, dass Svelte unseren Code analysiert, um Abhängigkeiten herauszufinden, also ist es besser, explizit darüber zu sein und nicht auf die Sichtbarkeit von zuweisbaren Variablen auf Komponentenebene zu vertrauen. Außerdem ist es eine gute Praxis, unseren Code klar und explizit darüber zu machen, welche Informationen es verwendet.
Der bisherige Code
Git
Um den aktuellen Stand des Codes zu sehen, wie er am Ende dieses Artikels sein sollte, greifen Sie so auf Ihre Kopie unseres Repos 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
Vergessen Sie nicht, 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 war's für den Moment! In diesem Artikel haben wir bereits den Großteil unserer gewünschten Funktionalität implementiert. Unsere App kann Aufgaben anzeigen, hinzufügen und löschen, ihren abgeschlossenen Status umschalten, anzeigen, wie viele davon abgeschlossen sind, und Filter anwenden.
Um zusammenzufassen, haben wir die folgenden Themen behandelt:
- Erstellen und Verwenden von Komponenten
- Statisches Markup in eine Live-Vorlage verwandeln
- Einbetten von JavaScript-Ausdrücken in unser Markup
- Iterieren über Listen mit der
{#each}
-Direktive - Übergeben von Informationen zwischen Komponenten mit Props
- Abhören von DOM-Ereignissen
- Deklarieren von reaktiven Anweisungen
- Grundlegendes Debuggen 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
- Explizite Definition unserer reaktiven Abhängigkeiten
Im nächsten Artikel fügen wir weitere Funktionen hinzu, die es den Benutzern ermöglichen, Aufgaben zu bearbeiten.