Ember-Interaktivität: Footer-Funktionalität, bedingtes Rendern
Hinweis: Die MDN Ember-Artikel werden nicht mehr gepflegt und 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.
Nun ist es an der Zeit, sich mit der Footer-Funktionalität in unserer App zu beschäftigen. Hier werden wir den Todo-Zähler so aktualisieren, dass die korrekte Anzahl der noch zu erledigenden Todos angezeigt wird, und korrektes Styling für erledigte Todos anwenden (d.h. wenn das Kontrollkästchen aktiviert wurde). Wir werden auch unseren "Clear completed"-Button verdrahten. Auf dem Weg dorthin lernen wir, wie man bedingtes Rendern in unseren Templates verwendet.
| Voraussetzungen: |
Es wird mindestens empfohlen, dass Sie mit den grundlegenden HTML, CSS und JavaScript Sprachen vertraut sind und Kenntnisse im Umgang mit der Terminal/Kommandozeile haben. Ein tieferes Verständnis moderner JavaScript-Features (wie Klassen, Module, usw.) wird äußerst hilfreich sein, da Ember stark von ihnen Gebrauch macht. |
|---|---|
| Ziel: | Um unser Lernen über Komponentenklassen fortzusetzen, beginnen wir mit dem bedingten Rendern und verdrahten einige unserer Footer-Funktionalität. |
Verbindung des Verhaltens im Footer
Um den Footer zu aktivieren, müssen wir die folgenden drei Funktionsbereiche implementieren:
- Einen noch ausstehenden Todo-Zähler.
- Filter für alle, aktive und erledigte Todos.
- Einen Button, um die erledigten Todos zu löschen.
-
Da wir vom Footer-Komponente aus auf unseren Dienst zugreifen müssen, müssen wir eine Klasse für den Footer erstellen. Geben Sie den folgenden Terminalbefehl ein, um dies zu tun:
bashember generate component-class footer -
Gehen Sie als nächstes zu der neu erstellten Datei
todomvc/app/components/footer.jsund aktualisieren Sie sie wie folgt:tsimport Component from "@glimmer/component"; import { inject as service } from "@ember/service"; export default class FooterComponent extends Component { @service("todo-data") todos; } -
Nun müssen wir zu unserer Datei
todo-data.jszurückkehren und einige Funktionen hinzufügen, die es uns ermöglichen, die Anzahl der unvollständigen Todos zurückzugeben (nützlich, um zu zeigen, wie viele noch übrig sind) und die erledigten Todos aus der Liste zu löschen (was die Funktion "Clear completed" erfordert).Fügen Sie in
todo-data.jsden folgenden Getter unterhalb des bestehendenall()Getters hinzu, um zu definieren, was die unvollständigen Todos tatsächlich sind:tsexport default class TodoDataService extends Service { // … get incomplete() { return this.todos.filter((todo) => !todo.isCompleted); } // … }Mit der
filter()-Methode fragen wir nach allen Todo-Elementen, bei denen die EigenschaftisCompletedgleichfalseist, und daisCompletedin unseremTodo-Objekt@trackedist, wird dieser Getter neu berechnet, wenn sich der Wert eines Objekts im Array ändert. -
Fügen Sie als nächstes die folgende Aktion unterhalb der bestehenden
add(text)-Aktion hinzu:tsexport default class TodoDataService extends Service { // … @action clearCompleted() { this.todos = this.incomplete; } // … }Dies ist sehr praktisch zum Löschen der Todos — wir müssen nur das
todos-Array auf die Liste der unvollständigen Todos setzen. -
Schließlich müssen wir diese neue Funktionalität in unserem
footer.hbs-Template nutzen. Gehen Sie jetzt zu dieser Datei. -
Ersetzen Sie zunächst diese Zeile:
hbs<strong>0</strong> todos leftMit dieser, die die Anzahl der unvollständigen Todos mit der Länge des
incomplete-Arrays füllt:hbs<strong>{{this.todos.incomplete.length}}</strong> todos left -
Ersetzen Sie als nächstes folgendes:
hbs<button type="button" class="clear-completed">Mit diesem:
hbs<button type="button" class="clear-completed" {{on 'click' this.todos.clearCompleted}}>
Nun wird die zuvor hinzugefügte Aktion clearCompleted() ausgeführt, wenn der Button geklickt wird.
Wenn Sie jetzt jedoch versuchen, auf die Schaltfläche "Clear Completed" zu klicken, scheint nichts zu passieren, da es derzeit keine Möglichkeit gibt, ein Todo als abgeschlossen zu markieren. Wir müssen das todo.hbs-Template an den Dienst anschließen, sodass das Aktivieren des relevanten Kontrollkästchens den Status jedes Todos ändert. Das werden wir als Nächstes tun.
Das Singular- und Pluralproblem von todo/todos
Das Obige ist in Ordnung, aber wir haben noch ein kleines Problem. Der "todos left"-Indikator sagt immer "x todos left", auch wenn nur ein Todo übrig bleibt, was grammatikalisch falsch ist!
Um dies zu beheben, müssen wir diesen Teil des Templates so aktualisieren, dass er bedingtes Rendern enthält. In Ember können Sie Teile des Templates bedingt rendern, indem Sie bedingten Inhalt verwenden; ein einfaches Blockbeispiel sieht etwa so aus:
{{#if this.thingIsTrue}} Content for the block form of "if"
{{/if}}
Versuchen wir also, diesen Teil von footer.hbs zu ersetzen:
<strong>{{this.todos.incomplete.length}}</strong> todos left
durch Folgendes:
<strong>{{this.todos.incomplete.length}}</strong>
{{#if this.todos.incomplete.length === 1}} todo
{{else}} todos
{{/if}} left
Dies wird uns jedoch einen Fehler geben — in Ember können diese einfachen if-Anweisungen derzeit nur eine true/false-Wert überprüfen, nicht einen komplexeren Ausdruck wie einen Vergleich. Um dies zu beheben, müssen wir einen Getter zu todo-data.js hinzufügen, der das Ergebnis von this.incomplete.length === 1 zurückgibt, und diesen dann in unserem Template aufrufen.
Fügen Sie diesen neuen Getter zu todo-data.js hinzu, direkt unter den vorhandenen Gettern. Beachten Sie, dass wir hier this.incomplete.length benötigen, nicht this.todos.incomplete.length, da wir dies im Dienst machen, wo der Getter incomplete() direkt verfügbar ist (im Template wurden die Inhalte des Dienstes als todos über die Zeile @service("todo-data") todos; in der Footerklasse verfügbar gemacht, daher dort this.todos.incomplete.length).
export default class TodoDataService extends Service {
// …
get todoCountIsOne() {
return this.incomplete.length === 1;
}
// …
}
Gehen Sie dann zurück zu footer.hbs und aktualisieren Sie den vorherigen bearbeiteten Abschnitt des Templates wie folgt:
<strong>{{this.todos.incomplete.length}}</strong>
{{#if this.todos.todoCountIsOne}}todo{{else}}todos{{/if}} left
Speichern und testen Sie nun, und Sie sehen, dass die korrekte Pluralisierung verwendet wird, wenn Sie nur ein Todo-Element haben!
Beachten Sie, dass dies die Blockform von if in Ember ist; Sie könnten auch die Inline-Form verwenden:
{{if this.todos.todoCountIsOne "todo" "todos"}}
Erledigung von Todos
Wie bei den anderen Komponenten benötigen wir eine Klasse, um auf den Dienst zuzugreifen.
Erstellen einer Todo-Klasse
-
Führen Sie den folgenden Befehl im Terminal aus:
bashember generate component-class todo -
Gehen Sie nun zur neu erstellten Datei
todomvc/app/components/todo.jsund aktualisieren Sie den Inhalt, um der Todo-Komponente Zugriff auf den Dienst zu geben:tsimport Component from "@glimmer/component"; import { inject as service } from "@ember/service"; export default class TodoComponent extends Component { @service("todo-data") todos; } -
Kehren Sie dann erneut zu unserer
todo-data.js-Dienstdatei zurück und fügen Sie die folgende Aktion direkt unterhalb der vorherigen hinzu, die es uns ermöglicht, den Abschlussstatus für jedes Todo umzuschalten:tsexport default class TodoDataService extends Service { // … @action toggleCompletion(todo) { todo.isCompleted = !todo.isCompleted; } // … }
Aktualisierung des Templates zur Anzeige des abgeschlossenen Status
Schließlich werden wir das todo.hbs-Template so bearbeiten, dass der Wert des Kontrollkästchens nun an die Eigenschaft isCompleted des Todos gebunden wird und dass bei einer Änderung die toggleCompletion()-Methode des Todo-Dienstes aufgerufen wird.
-
Finden Sie in
todo.hbszuerst die folgende Zeile:hbs<li>Und ersetzen Sie sie durch diese – Sie werden bemerken, dass wir hier einige bedingte Inhalte verwenden, um den Klassenwert bei Bedarf hinzuzufügen:
hbs<li class={{ if @todo.isCompleted 'completed' }}> -
Finden Sie als nächstes die folgende Zeile:
hbs<input aria-label="Toggle the completion of this todo" class="toggle" type="checkbox" >Und ersetzen Sie sie durch diese:
hbs<input class="toggle" type="checkbox" aria-label="Toggle the completion of this todo" checked={{ @todo.isCompleted }} {{ on 'change' (fn this.todos.toggleCompletion @todo) }} >Hinweis: Der obige Ausschnitt verwendet ein neues Ember-spezifisches Schlüsselwort —
fn.fnermöglicht Teilapplikationen, was ähnlich wiebindist, jedoch den Aufrufkontext niemals ändert; dies entspricht der Verwendung vonbindmit einemnull-Erstargument.
Versuchen Sie, den Entwicklungsserver neu zu starten und gehen Sie erneut zu localhost:4200, und Sie werden nun sehen, dass wir einen voll funktionsfähigen "todos left"-Zähler und eine Schaltfläche zum Löschen haben:

Wenn Sie sich fragen, warum wir das Umschalten nicht direkt in der Komponente durchführen, da die Funktion völlig eigenständig ist und nichts vom Dienst benötigt, dann ist es absolut richtig, diese Frage zu stellen! Da wir aber irgendwann alle Änderungen an der Todo-Liste in lokalem Speicher speichern oder synchronisieren wollen (siehe die Endversion der App), macht es Sinn, dass alle Operationen, die den Zustand ändern, an einem Ort zusammengefasst sind.
Zusammenfassung
Das reicht für jetzt. An diesem Punkt können wir nicht nur Todos als erledigt markieren, sondern sie auch löschen. Jetzt bleibt nur noch, die drei Filterlinks "All", "Active" und "Completed" im Footer zu verdrahten. Das werden wir im nächsten Artikel mit Routing tun.