Erweitertes Svelte: Reaktivität, Lebenszyklus, Barrierefreiheit
Hinweis: Die MDN Svelte Artikel werden nicht mehr gepflegt und werden in 3 Monaten (bis zum 20. August 2026) von der Website entfernt. Der Inhalt wird im MDN Museum archiviert. Weitere Informationen finden Sie in dieser Diskussion.
Im letzten Artikel haben wir unserer To-do-Liste mehr Funktionen hinzugefügt und begonnen, unsere App in Komponenten zu organisieren. In diesem Artikel werden wir die letzten Funktionen der App hinzufügen und unsere App weiter in Komponenten zerlegen. Wir werden lernen, wie man mit Problemen der Reaktivität im Zusammenhang mit der Aktualisierung von Objekten und Arrays umgeht. Um häufige Fallstricke zu vermeiden, müssen wir tiefer in das Reaktivitätssystem von Svelte eintauchen. Wir werden uns auch mit der Lösung einiger Barrierefreiheit-Fokusprobleme befassen und mehr.
| Voraussetzungen: |
Es wird mindestens empfohlen, dass Sie mit den Kernsprachen HTML, CSS und JavaScript vertraut sind und Kenntnisse über das Terminal/Kommandozeile haben. Sie benötigen ein Terminal mit installierten Node und npm, um Ihre App zu kompilieren und zu erstellen. |
|---|---|
| Ziel: | Erlernen einiger fortgeschrittener Svelte-Techniken zur Lösung von Reaktivitätsproblemen, Problemen der Tastaturzugänglichkeit im Zusammenhang mit dem Lebenszyklus von Komponenten und mehr. |
Wir werden uns auf einige Zugänglichkeitsprobleme im Zusammenhang mit der Fokusverwaltung konzentrieren. Dazu werden wir einige Techniken nutzen, um auf DOM-Knoten zuzugreifen und Methoden wie focus() und select() auszuführen. Wir werden auch sehen, wie man Ereignis-Listener auf DOM-Elementen deklarieren und aufräumen kann.
Wir müssen auch ein wenig über den Lebenszyklus von Komponenten lernen, um zu verstehen, wann diese DOM-Knoten in den DOM eingefügt und entfernt werden und wie wir auf sie zugreifen können. Wir werden auch über die action-Direktive lernen, die es uns ermöglicht, die Funktionalität von HTML-Elementen auf wiederverwendbare und deklarative Weise zu erweitern.
Schließlich werden wir ein wenig mehr über Komponenten lernen. Bisher haben wir gesehen, wie Komponenten Daten mittels Props teilen und mit ihren Eltern durch Ereignisse und bidirektionale Datenbindung kommunizieren können. Jetzt werden wir sehen, wie Komponenten auch Methoden und Variablen freigeben können.
Die folgenden neuen Komponenten werden im Verlauf des Artikels entwickelt:
MoreActions: Zeigt die Schaltflächen Alle überprüfen und Entfernte Aufgaben an und löst die entsprechenden Ereignisse aus, die erforderlich sind, um ihre Funktionalität zu steuern.NewTodo: Zeigt das<input>-Feld und die Hinzufügen-Schaltfläche zum Hinzufügen eines neuen To-dos an.TodosStatus: Zeigt die Statusüberschrift "x von y Elemente abgeschlossen" an.
Code zusammen mit uns
>Git
Klonen Sie das GitHub-Repository (falls Sie es noch nicht getan haben) mit:
git clone https://github.com/opensas/mdn-svelte-tutorial.git
Um zum aktuellen Zustand der App zu gelangen, führen Sie aus
cd mdn-svelte-tutorial/05-advanced-concepts
Oder laden Sie den Inhalt des Ordners direkt herunter:
npx degit opensas/mdn-svelte-tutorial/05-advanced-concepts
Vergessen Sie nicht, npm install && npm run dev auszuführen, um Ihre App im Entwicklungsmodus zu starten.
REPL
Um zusammen mit uns im REPL zu programmieren, beginnen Sie unter
https://svelte.dev/repl/76cc90c43a37452e8c7f70521f88b698?version=3.23.2
Arbeiten an der Komponente MoreActions
Jetzt werden wir die Schaltflächen Alle überprüfen und Entfernte Aufgaben angehen. Lassen Sie uns eine Komponente erstellen, die für die Darstellung der Schaltflächen und das Emittieren der entsprechenden Ereignisse verantwortlich ist.
-
Erstellen Sie eine neue Datei,
components/MoreActions.svelte. -
Wenn die erste Schaltfläche geklickt wird, emittieren wir ein
checkAllEreignis, um zu signalisieren, dass alle To-dos überprüft/ungeprüft werden sollten. Wenn die zweite Schaltfläche geklickt wird, emittieren wir einremoveCompletedEreignis, um zu signalisieren, dass alle abgeschlossenen To-dos entfernt werden sollten. Fügen Sie den folgenden Inhalt in IhreMoreActions.svelteDatei ein:svelte<script> import { createEventDispatcher } from "svelte"; const dispatch = createEventDispatcher(); let completed = true; const checkAll = () => { dispatch("checkAll", completed); completed = !completed; }; const removeCompleted = () => dispatch("removeCompleted"); </script> <div class="btn-group"> <button type="button" class="btn btn__primary" on:click={checkAll}>{completed ? 'Check' : 'Uncheck'} all</button> <button type="button" class="btn btn__primary" on:click={removeCompleted}>Remove completed</button> </div>Wir haben auch eine
completedVariable hinzugefügt, um zwischen dem Überprüfen und dem Entfernen aller Aufgaben zu wechseln. -
Zurück in
Todos.sveltewerden wir unsereMoreActionsKomponente importieren und zwei Funktionen erstellen, um die von derMoreActionsKomponente emittierten Ereignisse zu handhaben.Fügen Sie die folgende Importanweisung unter den bestehenden ein:
jsimport MoreActions from "./MoreActions.svelte"; -
Fügen Sie dann die beschriebenen Funktionen am Ende des
<script>Abschnitts hinzu:jsconst checkAllTodos = (completed) => todos.forEach((t) => (t.completed = completed)); const removeCompletedTodos = () => (todos = todos.filter((t) => !t.completed)); -
Gehen Sie nun zum unteren Ende des Markup-Abschnitts von
Todos.svelteund ersetzen Sie das<div class="btn-group">Element, das wir inMoreActions.sveltekopiert haben, durch einen Aufruf zurMoreActionsKomponente, wie folgt:svelte<!-- MoreActions --> <MoreActions on:checkAll={(e) => checkAllTodos(e.detail)} on:removeCompleted={removeCompletedTodos} /> -
OK, lassen Sie uns zurück zur App gehen und es ausprobieren. Sie werden feststellen, dass die Schaltfläche Entfernte Aufgaben gut funktioniert, aber die Schaltfläche Alle überprüfen/ Alle ungeprüft nur stillschweigend fehlschlägt.
Um herauszufinden, was hier passiert, müssen wir tiefer in die Svelte-Reaktivität eintauchen.
Reaktivitätsfallen: Aktualisieren von Objekten und Arrays
Um zu sehen, was passiert, können wir das todos Array von der checkAllTodos() Funktion aus in die Konsole protokollieren.
-
Aktualisieren Sie Ihre bestehende
checkAllTodos()Funktion wie folgt:jsconst checkAllTodos = (completed) => { todos.forEach((t) => (t.completed = completed)); console.log("todos", todos); }; -
Kehren Sie zu Ihrem Browser zurück, öffnen Sie Ihre DevTools-Konsole, und klicken Sie mehrmals auf Alle überprüfen/ Alle ungeprüft.
Sie werden feststellen, dass das Array jedes Mal erfolgreich aktualisiert wird, wenn Sie die Schaltfläche drücken (die todo Objekte' completed Eigenschaften werden zwischen true und false umgeschaltet), aber Svelte ist sich dessen nicht bewusst. Dies bedeutet auch, dass in diesem Fall eine reaktive Anweisung wie $: console.log('todos', todos) nicht sehr nützlich sein wird.
Um herauszufinden, warum dies passiert, müssen wir verstehen, wie die Reaktivität in Svelte beim Aktualisieren von Arrays und Objekten funktioniert.
Viele Web-Frameworks verwenden die Virtual-DOM-Technik, um die Seite zu aktualisieren. Im Grunde ist der virtuelle DOM eine im Speicher befindliche Kopie des Inhalts der Webseite. Das Framework aktualisiert diese virtuelle Darstellung, die dann mit dem "echten" DOM synchronisiert wird. Dies ist viel schneller als das direkte Aktualisieren des DOM und ermöglicht dem Framework, viele Optimierungstechniken anzuwenden.
Diese Frameworks führen standardmäßig unser gesamtes JavaScript bei jeder Änderung gegen diesen virtuellen DOM aus und wenden verschiedene Methoden an, um teure Berechnungen zwischenzuspeichern und die Ausführung zu optimieren. Sie machen wenig bis gar keine Versuche zu verstehen, was unser JavaScript-Code tut.
Svelte verwendet keine virtuelle DOM-Darstellung. Stattdessen parst und analysiert es unseren Code, erstellt einen Abhängigkeitsbaum und generiert dann das erforderliche JavaScript, um nur die Teile des DOM zu aktualisieren, die aktualisiert werden müssen. Dieser Ansatz generiert in der Regel optimales JavaScript mit minimalem Overhead, hat aber auch seine Grenzen.
Manchmal kann Svelte keine Änderungen an überwachten Variablen erkennen. Denken Sie daran, um Svelte mitzuteilen, dass sich eine Variable geändert hat, müssen Sie ihr einen neuen Wert zuweisen. Eine einfache Regel, die man sich merken sollte, ist, dass der Name der aktualisierten Variablen auf der linken Seite der Zuweisung stehen muss.
Zum Beispiel in folgendem Codeabschnitt:
const foo = obj.foo;
foo.bar = "baz";
Svelte wird Verweise auf obj.foo.bar nicht aktualisieren, es sei denn, Sie folgen es mit obj = obj. Das liegt daran, dass Svelte Objektverweise nicht nachverfolgen kann, sodass wir ihm explizit mitteilen müssen, dass sich obj geändert hat, indem wir eine Zuweisung ausführen.
Hinweis:
Wenn foo eine oberste Variable ist, können Sie Svelte leicht mitteilen, dass obj jedes Mal aktualisiert werden soll, wenn foo geändert wird, mit der folgenden reaktiven Anweisung: $: foo, obj = obj. Damit definieren wir foo als Abhängigkeit, und wann immer es sich ändert, wird Svelte obj = obj ausführen.
In unserer checkAllTodos() Funktion, wenn wir:
todos.forEach((t) => (t.completed = completed));
ausführen, wird Svelte todos nicht als geändert markieren, weil es nicht weiß, dass wir mit der Aktualisierung unserer t Variablen innerhalb der forEach() Methode auch das todos Array ändern. Und das macht Sinn, weil Svelte sonst die inneren Abläufe der forEach() Methode kennen müsste; das gleiche würde somit für jede Methode gelten, die an irgendein Objekt oder Array angehängt ist.
Es gibt jedoch verschiedene Techniken, die wir anwenden können, um dieses Problem zu lösen, und alle beinhalten die Zuweisung eines neuen Werts an die beobachtete Variable.
Wie wir bereits gesehen haben, könnten wir Svelte einfach dazu bringen, die Variable mit einer Selbstzuweisung zu aktualisieren, so wie diese:
const checkAllTodos = (completed) => {
todos.forEach((t) => (t.completed = completed));
todos = todos;
};
Das wird das Problem lösen. Intern wird Svelte todos als geändert markieren und die scheinbar redundante Selbstzuweisung entfernen. Abgesehen von der Tatsache, dass es seltsam aussieht, ist es völlig in Ordnung, diese Technik zu verwenden, und manchmal ist es der knappste Weg, dies zu tun.
Wir könnten auch das todos Array per Index erreichen, so wie diese:
const checkAllTodos = (completed) => {
todos.forEach((t, i) => (todos[i].completed = completed));
};
Zuweisungen zu Eigenschaften von Arrays und Objekten — z. B. obj.foo += 1 oder array[i] = x — funktionieren genauso wie Zuweisungen zu den Werten selbst. Wenn Svelte diesen Code analysiert, kann es erkennen, dass das todos Array modifiziert wird.
Eine andere Lösung ist es, ein neues Array an todos zuzuweisen, das eine Kopie aller To-dos mit der entsprechend aktualisierten completed Eigenschaft enthält, wie folgt:
const checkAllTodos = (completed) => {
todos = todos.map((t) => ({ ...t, completed }));
};
In diesem Fall verwenden wir die map() Methode, die ein neues Array mit den Ergebnissen der Ausführung der bereitgestellten Funktion für jedes Element zurückgibt. Die Funktion gibt eine Kopie jedes To-dos mithilfe der Spread-Syntax zurück und überschreibt die Eigenschaft des completed Werts entsprechend. Diese Lösung hat den zusätzlichen Vorteil, dass ein neues Array mit neuen Objekten zurückgegeben wird, wodurch das ursprüngliche todos Array vollständig vermieden wird.
Hinweis:
Svelte erlaubt uns, verschiedene Optionen zu spezifizieren, die beeinflussen, wie der Compiler funktioniert. Die <svelte:options immutable={true}/> Option sagt dem Compiler, dass Sie versprechen, keine Objekte zu mutieren. Dies ermöglicht es ihm, weniger konservativ zu sein, wenn es darum geht, zu überprüfen, ob sich Werte geändert haben, und einfacheren und leistungsfähigeren Code zu generieren. Für weitere Informationen über <svelte:options>, sehen Sie sich die Svelte Optionen Dokumentation an.
All diese Lösungen beinhalten eine Zuweisung, bei der die aktualisierte Variable auf der linken Seite der Gleichung steht. Jede dieser Techniken ermöglicht es Svelte, zu bemerken, dass unser todos Array modifiziert wurde.
Wählen Sie eine aus, und aktualisieren Sie Ihre checkAllTodos() Funktion gemäß den Anforderungen. Jetzt sollten Sie in der Lage sein, alle Ihre To-dos auf einmal zu überprüfen und zu entmarkieren. Probieren Sie es aus!
Unser MoreActions-Komponente fertigstellen
Wir werden unser Component ein kleines Detail zur Benutzerfreundlichkeit hinzufügen. Wir werden die Schaltflächen deaktivieren, wenn keine Aufgaben bearbeitet werden müssen. Dazu werden wir das todos Array als Prop empfangen und die disabled Eigenschaft jeder Schaltfläche entsprechend festlegen.
-
Aktualisieren Sie Ihre
MoreActions.svelteKomponente wie folgt:svelte<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); export let todos; let completed = true; const checkAll = () => { dispatch('checkAll', completed); completed = !completed; } const removeCompleted = () => dispatch('removeCompleted'); $: completedTodos = todos.filter((t) => t.completed).length; </script> <div class="btn-group"> <button type="button" class="btn btn__primary" disabled={todos.length === 0} on:click={checkAll}>{completed ? 'Check' : 'Uncheck'} all</button> <button type="button" class="btn btn__primary" disabled={completedTodos === 0} on:click={removeCompleted}>Remove completed</button> </div>Wir haben auch eine reaktive
completedTodosVariable deklariert, um die Entfernte Aufgaben Schaltfläche zu aktivieren oder zu deaktivieren. -
Vergessen Sie nicht, das Prop in
MoreActionsvon innenTodos.sveltezu übergeben, wo die Komponente aufgerufen wird:svelte<MoreActions {todos} on:checkAll={(e) => checkAllTodos(e.detail)} on:removeCompleted={removeCompletedTodos} />
Arbeiten mit dem DOM: Fokussierung auf die Details
Nachdem wir jetzt alle erforderlichen Funktionen der App fertiggestellt haben, konzentrieren wir uns auf einige Barrierefreiheit-Funktionen, die die Benutzerfreundlichkeit unserer App sowohl für Tastaturbenutzer als auch für Bildschirmlesegeräte verbessern werden.
Derzeit hat unsere App einige Probleme mit der Tastaturzugänglichkeit, die die Fokusverwaltung betreffen. Sehen wir uns diese Probleme an.
Erkunden der Tastaturzugänglichkeitsprobleme in unserer ToDo-App
Im Moment werden Tastaturbenutzer feststellen, dass der Fokusfluss unserer App nicht sehr vorhersehbar oder kohärent ist.
Wenn Sie auf das Eingabefeld oben in unserer App klicken, sehen Sie eine dicke, gestrichelte Umrandung um dieses Eingabefeld. Diese Umrandung ist Ihr visueller Indikator dafür, dass der Browser derzeit auf dieses Element fokussiert ist.
Wenn Sie ein Mausbenutzer sind, haben Sie diesen visuellen Hinweis möglicherweise übersprungen. Aber wenn Sie ausschließlich mit der Tastatur arbeiten, ist es von entscheidender Bedeutung zu wissen, welches Steuerelement den Fokus hat. Es zeigt uns, welches Steuerelement unsere Tastenanschläge empfangen wird.
Wenn Sie wiederholt die Tab-Taste drücken, sehen Sie den gestrichelten Fokusindikator zwischen allen fokussierbaren Elementen auf der Seite wechseln. Wenn Sie den Fokus auf die Bearbeiten Taste verschieben und Eingabetaste drücken, verschwindet plötzlich der Fokus, und Sie können nicht mehr erkennen, welches Steuerelement unsere Tastenanschläge empfangen wird.
Darüber hinaus geschieht nichts, wenn Sie die Esc- oder Eingabe-Taste Drücken. Und wenn Sie auf Abbrechen oder Speichern klicken, verschwindet der Fokus erneut. Für einen Benutzer, der mit der Tastatur arbeitet, wird dieses Verhalten bestenfalls verwirrend sein.
Wir möchten auch einige Funktionen zur Benutzerfreundlichkeit hinzufügen, wie z.B. die Deaktivierung der Speichern Taste, wenn erforderliche Felder leer sind, das Fokussieren bestimmter HTML-Elemente oder das automatische Auswählen von Inhalten, wenn ein Texteingabefeld den Fokus erhält.
Um all diese Funktionen umzusetzen, benötigen wir programmgesteuerten Zugriff auf DOM-Knoten, um Funktionen wie focus() und select() auszuführen. Wir werden auch addEventListener() und removeEventListener() verwenden müssen, um bestimmte Aufgaben auszuführen, wenn das Steuerelement den Fokus erhält.
Das Problem ist, dass all diese DOM-Knoten von Svelte zur Laufzeit dynamisch erstellt werden. Wir müssen also warten, bis sie erstellt und dem DOM hinzugefügt werden, um sie nutzen zu können. Dazu müssen wir etwas über den Komponentenlebenszyklus lernen, um zu verstehen, wann wir auf sie zugreifen können — mehr dazu später.
Erstellen einer NewTodo-Komponente
Beginnen wir damit, unser neues To-do-Formular in eine eigene Komponente auszugliedern. Mit unserem bisherigen Wissen können wir eine neue Komponenten-Datei erstellen und den Code anpassen, um ein addTodo Ereignis zu emittieren, wobei der Name des neuen To-dos zusammen mit den zusätzlichen Details übergeben wird.
-
Erstellen Sie eine neue Datei,
components/NewTodo.svelte. -
Fügen Sie die folgenden Inhalte ein:
svelte<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); let name = ''; const addTodo = () => { dispatch('addTodo', name); name = ''; } const onCancel = () => name = ''; </script> <form on:submit|preventDefault={addTodo} on:keydown={(e) => e.key === 'Escape' && onCancel()}> <h2 class="label-wrapper"> <label for="todo-0" class="label__lg">What needs to be done?</label> </h2> <input bind:value={name} type="text" id="todo-0" autoComplete="off" class="input input__lg" /> <button type="submit" disabled={!name} class="btn btn__primary btn__lg">Add</button> </form>Hier binden wir das
<input>an dienameVariable mitbind:value={name}und deaktivieren die Hinzufügen Taste, wenn sie leer ist (d.h. keinen Textinhalt hat) mitdisabled={!name}. Wir kümmern uns auch um die Esc-Taste miton:keydown={(e) => e.key === 'Escape' && onCancel()}}. Jedes Mal, wenn die Esc-Taste gedrückt wird, führen wironCancel()aus, was einfach dienameVariable löscht. -
Jetzt müssen wir es von innen importieren und in der
TodosKomponente verwenden und dieaddTodo()Funktion so aktualisieren, dass sie den Namen des neuen To-do empfängt.Fügen Sie die folgende
import-Anweisung unter den anderen inTodos.svelteein:jsimport NewTodo from "./NewTodo.svelte"; -
Und aktualisieren Sie die
addTodo()Funktion wie folgt:jsfunction addTodo(name) { todos = [...todos, { id: newTodoId, name, completed: false }]; }Die
addTodo()-Funktion empfängt jetzt direkt den Namen des neuen To-do, sodass wir dienewTodoName-Variable nicht mehr benötigen, um ihr ihren Wert zu geben. UnsereNewTodo-Komponente kümmert sich darum.Hinweis: Die
{ name }-Syntax ist nur eine Kurzform für{ name: name }. Diese stammt aus JavaScript selbst und hat nichts mit Svelte zu tun, außer dass sie einige Inspirationen für die Svelte-eigenen Kurzformen liefert. -
Ersetzen Sie schließlich den NewTodo-Formular-Markup durch einen Aufruf der
NewTodo-Komponente, wie folgt:svelte<!-- NewTodo --> <NewTodo on:addTodo={(e) => addTodo(e.detail)} />
Arbeiten mit DOM-Knoten unter Verwendung der bind:this={dom_node}-Direktive
Jetzt möchten wir, dass das <input>-Element der NewTodo-Komponente den Fokus jedes Mal wiedererlangt, wenn die Hinzufügen-Taste gedrückt wird. Dazu benötigen wir eine Referenz zum DOM-Knoten des Eingabefelds. Svelte bietet eine Möglichkeit, dies mit der bind:this={dom_node}-Direktive zu tun. Wenn angegeben, weist Svelte, sobald die Komponente montiert und der DOM-Knoten erstellt wurde, der angegebenen Variablen eine Referenz auf den DOM-Knoten zu.
Wir werden eine nameEl-Variable erstellen und sie an das Eingabefeld mit bind:this={nameEl} binden. Dann werden wir innerhalb addTodo(), nach dem Hinzufügen des neuen To-do, nameEl.focus() aufrufen, um das <input> erneut zu fokussieren. Wir werden dies auch tun, wenn der Benutzer die Esc-Taste drückt, mit der onCancel()-Funktion.
Aktualisieren Sie den Inhalt von NewTodo.svelte wie folgt:
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
let name = '';
let nameEl; // reference to the name input DOM node
const addTodo = () => {
dispatch('addTodo', name);
name = '';
nameEl.focus(); // give focus to the name input
}
const onCancel = () => {
name = '';
nameEl.focus(); // give focus to the name input
}
</script>
<form on:submit|preventDefault={addTodo} on:keydown={(e) => e.key === 'Escape' && onCancel()}>
<h2 class="label-wrapper">
<label for="todo-0" class="label__lg">What needs to be done?</label>
</h2>
<input bind:value={name} bind:this={nameEl} type="text" id="todo-0" autoComplete="off" class="input input__lg" />
<button type="submit" disabled={!name} class="btn btn__primary btn__lg">Add</button>
</form>
Probieren Sie die App aus: geben Sie einen neuen To-do-Namen in das <input>-Feld ein, drücken Sie Tab, um den Fokus auf die Hinzufügen-Schaltfläche zu geben, und drücken Sie dann Eingabetaste oder Esc, um zu sehen, wie das Eingabefeld den Fokus wiedererlangt.
Das Eingabefeld automatisch fokussieren
Die nächste Funktion, die wir unserer NewTodo-Komponente hinzufügen werden, ist ein autofocus-Prop, das es uns ermöglicht, zu spezifizieren, dass das <input>-Feld beim Laden der Seite fokussiert werden soll.
-
Unser erster Versuch sieht wie folgt aus: Versuchen wir, das
autofocus-Prop hinzuzufügen und einfachnameEl.focus()aus dem<script>-Block aufzurufen. Aktualisieren Sie den ersten Teil des<script>-Abschnitts vonNewTodo.svelte(die ersten vier Zeilen), sodass es so aussieht:svelte<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); export let autofocus = false; let name = ''; let nameEl; // reference to the name input DOM node if (autofocus) nameEl.focus(); -
Gehen Sie jetzt zurück zur
Todos-Komponente und übergeben Sie dasautofocus-Prop in den<NewTodo>-Komponentenaufruf, wie folgt:svelte<!-- NewTodo --> <NewTodo autofocus on:addTodo={(e) => addTodo(e.detail)} /> -
Wenn Sie die App jetzt ausprobieren, werden Sie feststellen, dass die Seite jetzt leer ist, und in Ihrer DevTools-Webkonsole wird ein Fehler ähnlich
TypeError: nameEl is undefinedangezeigt.
Um zu verstehen, was hier passiert, sprechen wir mehr über den Komponentenlebenszyklus, den wir bereits erwähnt haben.
Komponentenlebenszyklus und die onMount()-Funktion
Wenn eine Komponente instanziiert wird, führt Svelte den Initialisierungscode (d.h. den <script>-Abschnitt der Komponente) aus. Aber zu diesem Zeitpunkt sind alle Knoten, die die Komponente ausmachen, noch nicht an den DOM angehängt, tatsächlich existieren sie noch nicht einmal.
Wie kann man also wissen, wann die Komponente bereits erstellt und im DOM platziert wurde? Die Antwort ist, dass jede Komponente einen Lebenszyklus hat, der beginnt, wenn sie erstellt wird und endet, wenn sie zerstört wird. Es gibt eine Handvoll Funktionen, mit denen Sie zur richtigen Zeit während dieses Lebenszyklus Code ausführen können.
Die, die Sie am häufigsten verwenden werden, ist onMount(), die es uns ermöglicht, einen Rückruf auszuführen, sobald die Komponente im DOM platziert wurde. Lassen Sie es uns ausprobieren und sehen, was mit der nameEl-Variablen passiert.
-
Beginnen Sie damit, die folgende Zeile am Anfang des
<script>-Abschnitts vonNewTodo.sveltehinzuzufügen:jsimport { onMount } from "svelte"; -
Und diese Zeilen am Ende davon:
jsconsole.log("initializing:", nameEl); onMount(() => { console.log("mounted:", nameEl); }); -
Entfernen Sie nun die Zeile
if (autofocus) nameEl.focus(), um zu vermeiden, dass der Fehler, den wir vorher gesehen haben, ausgelöst wird. -
Die App wird nun wieder funktionieren, und Sie werden das Folgende in Ihrer Konsole sehen:
initializing: undefined mounted: <input id="todo-0" class="input input__lg" type="text" autocomplete="off">
Wie Sie sehen können, ist während der Initialisierung der Komponente
nameElundefiniert, was Sinn macht, da der<input>-Knoten noch nicht existiert. Nachdem die Komponente montiert wurde, hat Svelte dernameEl-Variablen eine Referenz auf den<input>-DOM-Knoten zugewiesen, dank derbind:this={nameEl}-Direktive. -
Um die Autofokus-Funktionalität zum Laufen zu bringen, ersetzen Sie den vorherigen
console.log()/onMount()-Block, den Sie hinzugefügt haben, mit diesem:jsonMount(() => autofocus && nameEl.focus()); // if autofocus is true, we run nameEl.focus() -
Gehen Sie zurück zu Ihrer App, und Sie werden jetzt sehen, dass das
<input>-Feld beim Laden der Seite fokussiert wird.
Hinweis: Sie können sich die anderen Lebenszyklusfunktionen in der Svelte-Dokumentation ansehen, und Sie können sie in Aktion im interaktiven Tutorial sehen.
Warten auf die Aktualisierung des DOM mit der tick()-Funktion
Nun werden wir die Fokusverwaltungsdetails der Todo-Komponente behandeln. Zuerst möchten wir, dass der Bearbeitungs-<input> einer Todo-Komponente den Fokus erhält, wenn wir den Bearbeitungsmodus durch Drücken der Schaltfläche Bearbeiten aufrufen. Auf die gleiche Art und Weise, wie wir es zuvor gesehen haben, werden wir eine nameEl-Variable innerhalb von Todo.svelte erstellen und nameEl.focus() aufrufen, nachdem wir die Variable editing auf true gesetzt haben.
-
Öffnen Sie die Datei
components/Todo.svelteund fügen Sie einenameEl-Variablendeklaration direkt unter der Bearbeitung und Namensdeklarationen hinzu:jslet nameEl; // reference to the name input DOM node -
Aktualisieren Sie jetzt Ihre
onEdit()-Funktion wie folgt:jsfunction onEdit() { editing = true; // enter editing mode nameEl.focus(); // set focus to name input } -
Und schließlich binden Sie
nameElan das<input>-Feld, indem Sie dieses wie folgt aktualisieren:svelte<input bind:value={name} bind:this={nameEl} type="text" id="todo-{todo.id}" autocomplete="off" class="todo-text" /> -
Wenn Sie die aktualisierte App ausprobieren, erhalten Sie jedoch einen Fehler in etwa "TypeError: nameEl is undefined" in der Konsole, wenn Sie die Bearbeiten Taste einer Aufgabe drücken.
Was passiert hier also? Wenn Sie den Zustand einer Komponente in Svelte aktualisieren, wird das DOM nicht sofort aktualisiert. Stattdessen wird bis zur nächsten Mikroaufgabe gewartet, um zu sehen, ob es noch andere Änderungen gibt, die angewendet werden müssen, einschließlich in anderen Komponenten. Dies vermeidet unnötige Arbeit und ermöglicht es dem Browser, Dinge effektiver zu bündeln.
In diesem Fall, wenn editing false ist, ist das Bearbeitungs-<input> nicht sichtbar, da es nicht im DOM existiert. Innerhalb der onEdit()-Funktion setzen wir editing = true und versuchen sofort danach auf die nameEl-Variable zuzugreifen und nameEl.focus() auszuführen. Das Problem hier ist, dass Svelte das DOM noch nicht aktualisiert hat.
Ein Weg, dieses Problem zu lösen, ist die Verwendung von setTimeout(), um den Aufruf von nameEl.focus() bis zum nächsten Ereigniszyklus zu verzögern und Svelte die Gelegenheit zu geben, das DOM zu aktualisieren.
Probieren Sie dies jetzt aus:
function onEdit() {
editing = true; // enter editing mode
setTimeout(() => nameEl.focus(), 0); // asynchronous call to set focus to name input
}
Die obige Lösung funktioniert, aber sie ist eher unelegant. Svelte bietet einen besseren Weg, um diese Fälle zu behandeln. Die tick()-Funktion gibt ein Versprechen zurück, das gelöst werden, sobald alle ausstehenden Zustandsänderungen auf das DOM angewendet wurden (oder sofort, wenn keine ausstehenden Zustandsänderungen vorhanden sind). Probieren wir es jetzt aus.
-
Importieren Sie zunächst
tickam Anfang des<script>-Abschnitts zusammen mit Ihrem vorhandenen Import:jsimport { tick } from "svelte"; -
Rufen Sie dann
tick()mitawaitaus einer async-Funktion auf; aktualisieren SieonEdit()wie folgt:jsasync function onEdit() { editing = true; // enter editing mode await tick(); nameEl.focus(); } -
Wenn Sie es jetzt ausprobieren, werden Sie sehen, dass alles wie erwartet funktioniert.
Hinweis:
Um ein weiteres Beispiel mit tick() zu sehen, besuchen Sie das Svelte-Tutorial.
Hinzufügen von Funktionalität zu HTML-Elementen mit der use:action-Direktive
Als nächstes möchten wir, dass der Name <input> automatisch den gesamten Text beim Fokus auswählt. Außerdem möchten wir dies auf eine Weise entwickeln, dass es einfach auf jedes HTML-<input> wiederverwendet und auf deklarative Weise angewendet werden kann. Wir werden diese Anforderung als Entschuldigung verwenden, um ein sehr leistungsstarkes Feature zu zeigen, das Svelte uns bietet, um Funktionalität zu normalen HTML-Elementen hinzuzufügen: Aktionen.
Um den Text eines DOM-Input-Knotens auszuwählen, müssen wir select() aufrufen. Um diese Funktion jedes Mal auszuführen, wenn der Knoten fokussiert wird, benötigen wir einen Ereignis-Listener in etwa wie folgt:
node.addEventListener("focus", (event) => node.select());
Und um Speicherlecks zu vermeiden, sollten wir auch die removeEventListener() Funktion aufrufen, wenn der Knoten zerstört wird.
Hinweis: Dies alles ist nur Standard-WebAPI-Funktionalität; nichts hiervon ist spezifisch für Svelte.
Wir könnten dies alles in unserer Todo-Komponente erreichen, wann immer wir das <input> zum DOM hinzufügen oder entfernen, aber wir müssten sehr vorsichtig sein, den Ereignis-Listener hinzuzufügen, nachdem der Knoten zum DOM hinzugefügt wurde, und den Listener zu entfernen, bevor der Knoten aus dem DOM entfernt wird. Darüber hinaus wäre unsere Lösung nicht sehr wiederverwendbar.
Hier kommen Svelte-Aktionen ins Spiel. Im Grunde genommen ermöglichen sie uns, eine Funktion jedes Mal auszuführen, wenn ein Element zum DOM hinzugefügt wurde, und nach dem Entfernen aus dem DOM.
In unserem sofortigen Anwendungsfall werden wir eine Funktion namens selectOnFocus() definieren, die einen Knoten als Parameter empfängt. Die Funktion fügt dem Knoten einen Ereignis-Listener hinzu, sodass, wenn immer er fokussiert wird, der Text ausgewählt wird. Dann wird ein Objekt mit einer destroy Eigenschaft zurückgegeben. Die destroy-Eigenschaft ist das, was Svelte ausführt, nachdem der Knoten aus dem DOM entfernt wurde. Hier werden wir den Listener entfernen, um sicherzustellen, dass wir keine Speicherlecks hinterlassen.
-
Lassen Sie uns die Funktion
selectOnFocus()erstellen. Fügen Sie das Folgende am Ende des<script>-Abschnitts vonTodo.svelteein:jsfunction selectOnFocus(node) { if (node && typeof node.select === "function") { // make sure node is defined and has a select() method const onFocus = (event) => node.select(); // event handler node.addEventListener("focus", onFocus); // when node gets focus call onFocus() return { destroy: () => node.removeEventListener("focus", onFocus), // this will be executed when the node is removed from the DOM }; } } -
Nun müssen wir den
<input>anweisen, diese Funktion mit deruse:actionDirektive zu verwenden:svelte<input use:selectOnFocus />Mit dieser Direktive teilen wir Svelte mit, dass er diese Funktion ausführen soll und den DOM-Knoten des
<input>als Parameter übergeben soll, sobald die Komponente im DOM montiert wird. Es wird auch dafür verantwortlich sein, diedestroyFunktion auszuführen, wenn die Komponente aus dem DOM entfernt wird. Mit deruseDirektive kümmert sich Svelte also um den Lebenszyklus der Komponente für uns.In unserem Fall würde unser
<input>so aussehen: aktualisieren Sie das erste Label/Eingabe-Paar der Komponente (innerhalb der Bearbeitungsvorlage) wie folgt:svelte<label for="todo-{todo.id}" class="todo-label">New name for '{todo.name}'</label> <input bind:value={name} bind:this={nameEl} use:selectOnFocus type="text" id="todo-{todo.id}" autocomplete="off" class="todo-text" /> -
Probieren Sie es aus. Gehen Sie zu Ihrer App, drücken Sie die Bearbeiten Taste einer Aufgabe und dann Tab um den Fokus vom
<input>zu entfernen. Klicken Sie nun auf das<input>, und Sie werden sehen, dass der gesamte Eingabetext ausgewählt ist.
Die Aktion wiederverwendbar machen
Jetzt machen wir diese Funktion wirklich wiederverwendbar für Komponenten. selectOnFocus() ist nur eine Funktion ohne Abhängigkeit von der Todo.svelte-Komponente, sodass wir sie einfach in eine Datei extrahieren und von dort verwenden können.
-
Erstellen Sie eine neue Datei,
actions.js, imsrc-Ordner. -
Geben Sie ihm den folgenden Inhalt:
jsexport function selectOnFocus(node) { if (node && typeof node.select === "function") { // make sure node is defined and has a select() method const onFocus = (event) => node.select(); // event handler node.addEventListener("focus", onFocus); // when node gets focus call onFocus() return { destroy: () => node.removeEventListener("focus", onFocus), // this will be executed when the node is removed from the DOM }; } } -
Importieren Sie sie jetzt von innen
Todo.svelte; fügen Sie die folgende Importanweisung direkt unter den anderen hinzu:jsimport { selectOnFocus } from "../actions.js"; -
Und entfernen Sie die
selectOnFocus()-Definition ausTodo.svelte, da wir sie dort nicht mehr benötigen.
Unsere Aktion wiederverwenden
Um die Wiederverwendbarkeit unserer Aktion zu demonstrieren, lassen Sie uns sie in NewTodo.svelte verwenden.
-
Importieren Sie
selectOnFocus()auch in diese Datei, wie zuvor:jsimport { selectOnFocus } from "../actions.js"; -
Fügen Sie die
use:selectOnFocusDirektive zum<input>hinzu, wie folgt:svelte<input bind:value={name} bind:this={nameEl} use:selectOnFocus type="text" id="todo-0" autocomplete="off" class="input input__lg" />
Mit wenigen Codezeilen können wir regulären HTML-Elementen Funktionalität hinzufügen, auf eine sehr wiederverwendbare und deklarative Weise. Es benötigt nur ein import und eine kurze Direktive wie use:selectOnFocus, die ihren Zweck klar beschreibt. Und wir können dies erreichen, ohne ein benutzerdefiniertes Wrapper-Element wie TextInput, MyInput oder ähnliches erstellen zu müssen. Außerdem können Sie einem Element so viele use:action Direktiven hinzufügen, wie Sie möchten.
Außerdem mussten wir uns nicht mit onMount(), onDestroy() oder tick() auseinandersetzen — die use Direktive übernimmt den Komponentenlebenszyklus für uns.
Andere Aktionen Verbesserungen
Im vorherigen Abschnitt, während wir mit den Todo-Komponenten arbeiteten, mussten wir uns mit bind:this, tick() und async Funktionen nur auseinandersetzen, um unserem <input> den Fokus zu geben, sobald es dem DOM hinzugefügt wurde.
-
So können wir es stattdessen mit Aktionen implementieren:
jsconst focusOnInit = (node) => node && typeof node.focus === "function" && node.focus(); -
Und dann brauchen wir in unserem Markup nur eine weitere
use:-Direktive hinzuzufügen:svelte<input bind:value={name} use:selectOnFocus use:focusOnInit /> -
Unsere
onEdit()-Funktion kann jetzt viel einfacher sein:jsfunction onEdit() { editing = true; // enter editing mode }
Als letztes Beispiel, bevor wir weitermachen, gehen wir zurück zu unserer Todo.svelte-Komponente und geben der Bearbeiten Taste den Fokus, nachdem der Benutzer Speichern oder Abbrechen gedrückt hat.
Wir könnten versuchen, unsere focusOnInit Aktion einfach wiederzuverwenden, indem wir use:focusOnInit zur Bearbeiten Taste hinzufügen. Aber wir würden einen subtilen Fehler einführen. Wenn Sie ein neues To-do hinzufügen, wird der Fokus auf die Bearbeiten Taste des neu hinzugefügten To-dos gelegt. Das liegt daran, dass die focusOnInit Aktion ausgeführt wird, wenn die Komponente erstellt wird.
Das ist nicht das, was wir wollen — wir möchten, dass die Bearbeiten Taste den Fokus nur dann erhält, wenn der Benutzer auf Speichern oder Abbrechen gedrückt hat.
-
Gehen Sie also zurück zu Ihrer
Todo.svelte-Datei. -
Zuerst erstellen wir eine Flagge namens
editButtonPressedund initialisieren sie auffalse. Fügen Sie diese direkt unter Ihren anderen Variablendeklarationen hinzu:jslet editButtonPressed = false; // track if edit button has been pressed, to give focus to it after cancel or save -
Als nächstes werden wir die Funktionalität der Bearbeiten Taste ändern, um diese Flagge zu speichern, und die Aktion dafür erstellen. Aktualisieren Sie die Funktion
onEdit()wie folgt:jsfunction onEdit() { editButtonPressed = true; // user pressed the Edit button, focus will come back to the Edit button editing = true; // enter editing mode } -
Darunter fügen Sie die folgende Definition für
focusEditButton()hinzu:jsconst focusEditButton = (node) => editButtonPressed && node.focus(); -
Schließlich verwenden wir die
focusEditButtonAktion auf der Bearbeiten Taste, wie folgt:svelte<button type="button" class="btn" on:click={onEdit} use:focusEditButton> Edit<span class="visually-hidden"> {todo.name}</span> </button> -
Gehen Sie zurück und probieren Sie Ihre App erneut. Jetzt wird jedes Mal, wenn die Bearbeiten Taste dem DOM hinzugefügt wird, die
focusEditButtonAktion ausgeführt, aber nur, wenn dieeditButtonPressedFlagge auftruegesetzt ist, wird der Fokus auf die Taste gegeben.
Hinweis:
Wir haben kaum an der Oberfläche von Aktionen gekratzt. Aktionen können auch reaktive Parameter haben, und Svelte lässt uns erkennen, wann sich einer dieser Parameter ändert. So können wir Funktionalität hinzufügen, die sich nahtlos in das Svelte-Reaktiersystem integriert. Für eine detailliertere Einführung in Aktionen sollten Sie die Svelte use:action-Dokumentation in Betracht ziehen.
Komponentenbindung: Freigeben von Komponentenmethoden und -variablen mit der bind:this={component}-Direktive
Es gibt noch eine Barrierefreiheit-Belästigung. Wenn der Benutzer die Löschen Taste drückt, verschwindet der Fokus.
Die letzte Funktion, die wir in diesem Artikel betrachten werden, beinhaltet das Setzen des Fokus auf die Statusüberschrift, nachdem ein To-do gelöscht wurde.
Warum die Statusüberschrift? In diesem Fall wurde das Element, das den Fokus hatte, gelöscht, und es gibt keinen klaren Kandidaten, um den Fokus zu erhalten. Wir haben die Statusüberschrift gewählt, weil sie in der Nähe der To-do Liste ist, und es ist eine Möglichkeit, ein visuelles Feedback über die Entfernung der Aufgabe zu geben, sowie anzuzeigen, was den Bildschirmlesegeräte-Benutzern passiert ist.
Zuerst extrahieren wir die Statusüberschrift in eine eigene Komponente.
-
Erstellen Sie eine neue Datei,
components/TodosStatus.svelte. -
Fügen Sie die folgenden Inhalte hinzu:
svelte<script> export let todos; $: totalTodos = todos.length; $: completedTodos = todos.filter((todo) => todo.completed).length; </script> <h2 id="list-heading"> {completedTodos} out of {totalTodos} items completed </h2> -
Importieren Sie die Datei am Anfang von
Todos.svelte, indem Sie die folgendeimport-Anweisung unter den anderen hinzufügen:jsimport TodosStatus from "./TodosStatus.svelte"; -
Ersetzen Sie die
<h2>-Statusüberschrift innerhalbTodos.sveltedurch einen Aufruf zurTodosStatus-Komponente, dietodosals Prop übergibt, wie folgt:svelte<TodosStatus {todos} /> -
Sie können auch ein wenig aufräumen und die
totalTodosundcompletedTodosVariablen ausTodos.svelteentfernen. Entfernen Sie einfach die$: totalTodos = …und die$: completedTodos = …Linien, und entfernen Sie auch die Referenz zutotalTodos, wenn wirnewTodoIdberechnen und verwenden stattdessentodos.length. Ersetzen Sie dazu den Block, der mitlet newTodoIdbeginnt, durch folgenden:js$: newTodoId = todos.length ? Math.max(...todos.map((t) => t.id)) + 1 : 1; -
Alles funktioniert wie erwartet — wir haben gerade das letzte Stück Markup in seine eigene Komponente extrahiert.
Nun müssen wir eine Möglichkeit finden, der <h2>-Statusbeschriftung den Fokus zu geben, nachdem ein To-do entfernt wurde.
Wir haben bisher gesehen, wie man Informationen über Props an eine Komponente sendet und wie eine Komponente mit ihrem Elternteil kommunizieren kann, indem sie Ereignisse emittiert oder eine bidirektionale Datenbindung verwendet. Die untergeordnete Komponente könnte eine Referenz auf den <h2>-Knoten erhalten, indem sie bind:this={dom_node} verwendet und ihn nach außen mit einer bidirektionalen Datenbindung freigibt. Aber dies würde die Kapselung der Komponente brechen; das Setzen des Fokus darauf sollte ihre eigene Verantwortung sein.
Wir benötigen also, dass die TodosStatus-Komponente eine Methode bereitstellt, die ihr Elternteil aufrufen kann, um ihr den Fokus zu geben. Es ist ein sehr häufiges Szenario, dass eine Komponente einige Verhaltensweisen oder Informationen an den Verbraucher weiterleiten muss; sehen wir, wie wir dies mit Svelte erreichen können.
Wir haben bereits gesehen, dass Svelte export let varname = … verwendet, um Props zu deklarieren. Aber wenn Sie anstelle von let const, class oder function exportieren, ist sie außerhalb der Komponente schreibgeschützt. Funktionsausdrücke sind jedoch gültige Props. Im folgenden Beispiel sind die ersten drei Deklarationen Props, und der Rest sind exportierte Werte:
<script>
export let bar = "optional default initial value"; // prop
export let baz = undefined; // prop
export let format = (n) => n.toFixed(2); // prop
// these are readonly
export const thisIs = "readonly"; // read-only export
export function greet(name) {
// read-only export
alert(`Hello, ${name}!`);
}
export const greet = (name) => alert(`Hello, ${name}!`); // read-only export
</script>
Mit diesem Wissen gehen wir zu unserem Anwendungsfall zurück. Wir erstellen eine Funktion namens focus(), die den Fokus auf die <h2>-Überschrift gibt. Dazu benötigen wir eine headingEl-Variable, um die Referenz auf den DOM-Knoten zu halten, und müssen sie an das <h2>-Element binden, indem wir bind:this={headingEl} verwenden. Unsere Fokusmethode führt einfach headingEl.focus() aus.
-
Aktualisieren Sie den Inhalt von
TodosStatus.sveltewie folgt:svelte<script> export let todos; $: totalTodos = todos.length; $: completedTodos = todos.filter((todo) => todo.completed).length; let headingEl; export function focus() { // shorter version: export const focus = () => headingEl.focus() headingEl.focus(); } </script> <h2 id="list-heading" bind:this={headingEl} tabindex="-1"> {completedTodos} out of {totalTodos} items completed </h2>Beachten Sie, dass wir ein
tabindex-Attribut zur<h2>-Element hinzugefügt haben, damit das Element den Fokus programmatisch erhalten kann.Wie wir bereits gesehen haben, gibt uns die Verwendung der
bind:this={headingEl}-Direktive eine Referenz auf den DOM-Knoten in der VariableheadingEl. Dann verwenden wirexport function focus(), um eine Funktion bereitzustellen, die den Fokus auf die<h2>-Überschrift gibt.Wie können wir auf diese exportierten Werte von den Eltern aus zugreifen? Genauso wie Sie mit der
bind:this={dom_node}-Direktive an DOM-Elemente binden können, können Sie auch mitbind:this={component}an Komponenteninstanzen binden. Wenn Siebind:thisauf einem HTML-Element verwenden, erhalten Sie eine Referenz auf den DOM-Knoten, und wenn Sie es auf einer Svelte-Komponente verwenden, erhalten Sie eine Referenz auf die Instanz dieser Komponente. -
Um an die Instanz von
TodosStatuszu binden, erstellen wir zuerst einetodosStatus-Variable inTodos.svelte. Fügen Sie die folgende Zeile unter Ihren Importanweisungen hinzu:jslet todosStatus; // reference to TodosStatus instance -
Fügen Sie dann eine
bind:this={todosStatus}-Direktive in den Aufruf ein, wie folgt:svelte<!-- TodosStatus --> <TodosStatus bind:this={todosStatus} {todos} /> -
Nun können wir die Methode
exported focus()aus unsererremoveTodo()-Funktion aufrufen:jsfunction removeTodo(todo) { todos = todos.filter((t) => t.id !== todo.id); todosStatus.focus(); // give focus to status heading } -
Gehen Sie zurück zu Ihrer App. Jetzt wird die Statusüberschrift bei jedem Löschen einer Aufgabe fokussiert. Dies ist nützlich, um die Änderung der Anzahl der Aufgaben hervorzuheben, sowohl für sehende Benutzer als auch für Benutzer von Bildschirmlesegeräten.
Hinweis:
Sie fragen sich vielleicht, warum wir eine neue Variable für die Komponentenbindung deklarieren müssen. Warum können wir nicht einfach TodosStatus.focus() aufrufen? Es könnten mehrere TodosStatus-Instanzen aktiv sein, daher benötigen wir eine Möglichkeit, auf jede bestimmte Instanz zu verweisen. Deshalb müssen Sie eine Variable angeben, um jede spezifische Instanz zu binden.
Der bisherige Code
>Git
Um den Stand des Codes zu sehen, wie er am Ende dieses Artikels aussehen sollte, greifen Sie auf Ihre Kopie unseres Repos wie folgt zu:
cd mdn-svelte-tutorial/06-stores
Oder laden Sie den Inhalt des Ordners direkt herunter:
npx degit opensas/mdn-svelte-tutorial/06-stores
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/d1fa84a5a4494366b179c87395940039?version=3.23.2
Zusammenfassung
In diesem Artikel haben wir alle erforderlichen Funktionen zu unserer App hinzugefügt und eine Reihe von Barrierefreiheits- und Benutzerfreundlichkeitsproblemen behandelt. Wir haben auch unsere App in handhabbare Komponenten aufgeteilt, von denen jede eine eindeutige Verantwortung hat.
In der Zwischenzeit haben wir einige fortgeschrittene Svelte-Techniken gesehen, wie zum Beispiel:
- Umgang mit Reaktivitätsproblemen beim Aktualisieren von Objekten und Arrays
- Arbeiten mit DOM-Knoten unter Verwendung von
bind:this={dom_node}(Bindung von DOM-Elementen) - Verwendung der Komponentenlebenszyklus
onMount()-Funktion - Erzwingen, dass Svelte ausstehende Zustandsänderungen mit der
tick()-Funktion auflöst - Hinzufügen von Funktionalität zu HTML-Elementen auf wiederverwendbare und deklarative Weise mit der
use:action-Direktive - Zugriff auf Komponentenmethoden mit
bind:this={component}(Bindung von Komponenten)
Im nächsten Artikel werden wir sehen, wie wir Stores verwenden, um zwischen Komponenten zu kommunizieren, und wie wir Animationen zu unseren Komponenten hinzufügen.