Cyber Monday Sale 40% off unlimited courses & creative assets! 40% off unlimited assets! Save Now
Advertisement
  1. Web Design
  2. JavaScript

Wie kann man eine To-Do-App mit Vanilla JavaScript erstellen (und lokalem Speicher)?

by
Read Time:13 minsLanguages:

German (Deutsch) translation by Katharina Grigorovich-Nevolina (you can also view the original English article)

In diesem Tutorial werden wir unsere Front-End-Fähigkeiten verbessern, indem wir lernen, eine „handgemachte“ To-Do-App zu erstellen. Zum Erstellen werden keine JavaScript-Frameworks verwendet. Wir verwenden nur HTML, CSS und Vanille-JavaScript.

Was werden wir erstellen?

Hier ist ein Einführungsvideo, das die Funktionalität der JavaScript-App demonstriert, die wir erstellen werden. Benutzer können Aufgaben hinzufügen, als erledigt markieren und entfernen. Die Aufgabensummen und ihre Status werden in der Statusleiste angezeigt:

Hier ist die Demo zu Codepen, mit der Sie spielen können:

Hinweis: Dies ist kein Einführungs-Tutorial. Es wird davon ausgegangen, dass Sie mit den wichtigsten Front-End-Kenntnissen wie CSS Grid, Flexbox, ES6, JavaScript-Arrays usw. vertraut sind. Für diese Demonstration hat es auch keine Priorität, die App vollständig zugänglich zu machen.

1. Beginnen Sie mit den erforderlichen Assets

Um das Layout ein bisschen einzigartiger zu gestalten, verwenden wir einige handgefertigte SVG-Illustrationen und eine benutzerdefinierte Schriftart aus Envato Elements.

SUMMER - FONT PACKSUMMER - FONT PACKSUMMER - FONT PACK
SOMMER - FONT PACK auf Envato Elements

Es ist erwähnenswert, dass die meisten dieser Assets aus einem früheren Tutorial stammen. Tatsächlich werden wir auch viele der Positionierungstechniken verwenden, die wir in diesem Tutorial gelernt haben. Es lohnt sich also, sie zu lesen.

How to Build a Responsive Handmade SVG FormHow to Build a Responsive Handmade SVG FormHow to Build a Responsive Handmade SVG Form

2. Weiter mit der Seiten-Markup

Wir beginnen mit einer SVG und einem div-Container:

SVG Sprites

Wie schon in der Vergangenheit haben wir als bewährte Methode alle SVGs als symbols in einem SVG-Sprite-Container gespeichert. Anschließend rendern wir sie bei Bedarf auf dem Bildschirm, indem wir das use-Element aufrufen.

Hier ist das Markup für das SVG-Sprite:

Beachten Sie das preserveAttributerveAspectRatio="none", das wir den meisten Abbildungen beigefügt haben. Wir haben dies getan, da unsere Symbole, wie wir später sehen werden, skaliert werden und ihre ursprünglichen Abmessungen verlieren.

Container

Der Container enthält ein Formular, ein div-Element und eine leere geordnete Liste:

Innerhalb des Formulars haben wir eine Eingabe- und eine Senden-Schaltfläche zusammen mit den zugehörigen SVGs:

Beachten Sie das name-Attribut, das wir dem Eingabefeld hinzugefügt haben. Später verwenden wir dieses Attribut, um nach dem Absenden des Formulars auf den Eingabewert zuzugreifen.

Hinweis: In unserer Demo funktioniert das autofocus-Attribut des Textfelds nicht. Tatsächlich wird der folgende Fehler ausgegeben, den Sie sehen können, wenn Sie Ihre Browserkonsole öffnen:

The cross-origin error due to the autofocus attributeThe cross-origin error due to the autofocus attributeThe cross-origin error due to the autofocus attribute

Wenn Sie diese App jedoch lokal ausführen (nicht als Codepen-Projekt), tritt dieses Problem nicht auf. Alternativ können Sie den Fokus über JavaScript festlegen.

Innerhalb des div platzieren wir drei verschachtelte divs und das zugehörige SVG. In diesem Abschnitt verfolgen wir die Gesamtzahl der verbleibenden und erledigten Aufgaben:

Schließlich werden die Elemente der geordneten Liste dynamisch über JavaScript hinzugefügt.

3. Definieren Sie einige grundlegende Stile

Wenn das Markup fertig ist, fahren wir mit einigen Reset-Stilen fort:

4. Legen Sie die Hauptstile fest

Lassen Sie uns nun die Hauptstile unserer App diskutieren.

Containerstile

Der Container hat eine maximale Breite mit horizontal zentriertem Inhalt:

Formularstile

Auf kleinen Bildschirmen werden alle Formularelemente gestapelt:

The form layout on small screensThe form layout on small screensThe form layout on small screens

In Ansichtsfenstern mit einer Breite von 600 Pixel und mehr ändert sich das Formularlayout jedoch wie folgt:

The form layout on medium screens and aboveThe form layout on medium screens and aboveThe form layout on medium screens and above

Beachten wir zwei Dinge:

  • In weiten Ansichtsfenstern ist die Eingabe doppelt so groß wie die Schaltfläche.
  • Die SVGs sind absolut positionierte Elemente und befinden sich unter ihrer angrenzenden Formularsteuerung. Eine ausführlichere Erklärung finden Sie in diesem vorherigen Tutorial.

Hier sind die Stile für diesen Abschnitt:

Statistik Stile

Schauen wir uns als nächstes die Statusleiste an, die uns einen kurzen Bericht über die Gesamtzahl der Aufgaben gibt.

Auf kleinen Bildschirmen sieht es wie folgt aus:

The stats layout on small screensThe stats layout on small screensThe stats layout on small screens

Bei Ansichtsfenstern mit einer Breite von 600 Pixel und mehr sollte sich dies jedoch wie folgt ändern:

The stats layout on medium screens and aboveThe stats layout on medium screens and aboveThe stats layout on medium screens and above

Beachten wir zwei Dinge:

  • In breiten Ansichtsfenstern haben alle untergeordneten div-Elemente die gleiche Breite.
  • Ähnlich wie bei den vorherigen SVGs ist auch diese absolut positioniert und fungiert als Hintergrundbild, das den gesamten Abschnitt abdeckt.

Die verwandten Stile:

Aufgabenstile

Das Aufgabenlayout, das wir im nächsten Abschnitt dynamisch generieren, sieht folgendermaßen aus:

The tasks layoutThe tasks layoutThe tasks layout

Jede Aufgabe, die durch ein li dargestellt wird, besteht aus zwei Teilen.

The markup representation of a taskThe markup representation of a taskThe markup representation of a task

Im ersten Teil wird ein Kontrollkästchen zusammen mit dem Aufgabennamen angezeigt. Im zweiten Teil sehen Sie eine Schaltfläche zum Löschen, um die Aufgabe zu entfernen.

Hier sind die verwandten Stile:

Wenn eine Aufgabe unvollständig ist, wird ein leeres Kontrollkästchen angezeigt. Wenn eine Aufgabe als erledigt markiert ist, wird ein Häkchen angezeigt. Zusätzlich erhält der Name eine Deckkraft von 50% sowie eine Linie durch ihn.

Hier sind die Stile, die für dieses Verhalten verantwortlich sind:

Im Folgenden finden Sie die Stile für die Schaltfläche "Löschen":

5. Fügen Sie das JavaScript hinzu

An diesem Punkt sind wir bereit, die Kernfunktionalität unserer App zu erstellen. Lassen Sie es uns tun!

Beim Einreichen des Formulars

Jedes Mal, wenn ein Benutzer das Formular durch Drücken der Eingabetaste oder der Schaltfläche "Senden" sendet, gehen wir wie folgt vor:

  1. Verhindern Sie das Senden des Formulars, wodurch ein erneutes Laden der Seite verhindert wird.
  2. Holen Sie sich den Wert, der im Eingabefeld enthalten ist.
  3. Angenommen, das Eingabefeld ist nicht leer, erstellen wir ein neues Objektliteral, das die Aufgabe darstellt. Jede Aufgabe hat eine eindeutige ID und einen Namen und ist standardmäßig aktiv (nicht abgeschlossen).
  4. Fügen Sie diese Aufgabe dem tasks-Array hinzu.
  5. Speichern Sie das Array im lokalen Speicher. Der lokale Speicher unterstützt nur Zeichenfolgen. Dazu müssen wir die Methode JSON.stringify() verwenden, um die Objekte im Array in Zeichenfolgen zu konvertieren.
  6. Rufen Sie die Funktion createTask() auf, um die Aufgabe auf dem Bildschirm visuell darzustellen.
  7. Löschen Sie das Formular.
  8. Konzentrieren Sie sich auf das Eingabefeld.

Hier ist der relevante Code:

Erstellen Sie eine Aufgabe

Die Funktion createTask() ist für die Erstellung des Markups der Aufgabe verantwortlich.

Hier ist zum Beispiel die Struktur für die Aufgabe "Go for a walk": 

The markup structure for a taskThe markup structure for a taskThe markup structure for a task

Zwei Dinge sind hier wichtig:

  • Wenn die Aufgabe abgeschlossen ist, wird das Häkchen angezeigt.
  • Wenn die Aufgabe nicht abgeschlossen ist, erhält das span-Element das Attribut contenteditable. Dieses Attribut gibt uns die Möglichkeit, seinen Namen zu bearbeiten/aktualisieren.

Unten ist die Syntax für diese Funktion:

Aktualisieren Sie eine Aufgabe

Eine Aufgabe kann auf zwei verschiedene Arten aktualisiert werden:

  • Durch Ändern des Status von "unvollständig" in "abgeschlossen" und umgekehrt.
  • Durch Ändern des Namens für den Fall, dass die Aufgabe unvollständig ist. Denken Sie daran, dass in diesem Fall das span-Element das Attribut contenteditable hat.

Um diese Änderungen im Auge zu behalten, nutzen wir das input-Ereignis. Dies ist ein akzeptables Ereignis für uns, da es sowohl für input-Elemente als auch für Elemente mit aktiviertem contenteditable gilt.

Das Schwierige ist, dass wir dieses Ereignis nicht direkt an die Zielelemente (Kontrollkästchen, span) anhängen können, da diese dynamisch erstellt werden und beim Laden der Seite nicht Teil des DOM sind.

Dank der Ereignisdelegation hängen wir das input-Ereignis an die übergeordnete Liste an, die Teil des anfänglichen Markups ist. Anschließend überprüfen wir über die target-Eigenschaft dieses Ereignisses die Elemente, bei denen das Ereignis aufgetreten ist, und rufen die Funktion updateTask() auf:

In der Funktion updateTask() führen wir die folgenden Schritte aus:

  1. Besorgen Sie sich die Aufgabe, die aktualisiert werden muss.
  2. Überprüfen Sie das Element, das das Ereignis ausgelöst hat. Wenn das Element das Attribut contenteditable hat (d. h. Es ist das span-Element), setzen wir den Namen der Aufgabe gleich dem Textinhalt des span.
  3. Andernfalls (d. h. Es ist das Kontrollkästchen) schalten wir den Status der Aufgabe und das checked-Attribut um. Außerdem schalten wir das contenteditable-Attribut der angrenzenden span um.
  4. Aktualisieren Sie den Wert des tasks-Schlüssels im lokalen Speicher.
  5. Rufen Sie die Funktion countTasks() auf.

Hier ist die Syntax für diese Funktion:

Entfernen Sie eine Aufgabe

Wir können eine Aufgabe über die Schaltfläche "Schließen" entfernen.

Button for removing a taskButton for removing a taskButton for removing a task

Ähnlich wie beim Aktualisierungsvorgang können wir dieser Schaltfläche kein Ereignis direkt zuordnen, da sie sich beim Laden der Seite nicht im DOM befindet.

Dank der Ereignisdelegation fügen wir der übergeordneten Liste ein click-Ereignis hinzu und führen die folgenden Aktionen aus:

  1. Überprüfen Sie, ob das Element, auf das geklickt wird, die Schaltfläche "Schließen" oder die untergeordnete SVG-Datei ist.
  2. In diesem Fall ermitteln wir die id des übergeordneten Listenelements.
  3. Übergeben Sie diese id an die Funktion removeTask().

Hier ist der relevante Code:

In der Funktion removeTask() führen wir die folgenden Schritte aus:

  1. Entfernen Sie die zugehörige Aufgabe aus dem tasks-Array.
  2. Aktualisieren Sie den Wert des tasks-Schlüssels im lokalen Speicher.
  3. Entfernen Sie das zugehörige Listenelement.
  4. Rufen Sie die Funktion countTasks() auf.

Hier ist die Syntax für diese Funktion:

Aufgaben zählen

Wie bereits erwähnt, enthalten viele der oben genannten Funktionen die Funktion countTask().

Seine Aufgabe besteht darin, die Aufgaben auf Änderungen (Hinzufügungen, Aktualisierungen, Löschungen) zu überwachen und den Inhalt der zugehörigen Elemente zu aktualisieren.

Count tasksCount tasksCount tasks

Hier ist seine Unterschrift:

Verhindern Sie das Hinzufügen neuer Zeilen

Jedes Mal, wenn ein Benutzer den Namen einer Aufgabe aktualisiert, sollte er keine neuen Zeilen durch Drücken der Eingabetaste erstellen können.

Prevent multi linesPrevent multi linesPrevent multi lines

Um diese Funktionalität zu deaktivieren, nutzen wir erneut die Ereignisdelegation und hängen das keydown-Ereignis wie folgt an die Liste an:

Beachten Sie, dass in diesem Szenario nur die span-Elemente dieses Ereignis auslösen können, sodass keine zusätzliche Prüfung wie folgt erforderlich ist:

Daten beim Laden der Seite beibehalten

Wenn wir den Browser schließen und zum Demo-Projekt navigieren, verschwinden unsere Aufgaben.

Aber warten Sie, das ist nicht 100% wahr! Denken Sie daran, dass wir bei jeder Aufgabenmanipulation auch das tasks-Array im lokalen Speicher speichern. Um beispielsweise in Chrome die lokalen Speicherschlüssel und -werte anzuzeigen, klicken Sie auf die Registerkarte Anwendung, erweitern Sie das Menü Lokaler Speicher und klicken Sie schließlich auf eine Domäne, um deren Schlüssel-Wert-Paare anzuzeigen.

In meinem Fall sind hier die Werte für den tasks-Schlüssel:

An example with local storageAn example with local storageAn example with local storage

Um diese Aufgaben anzuzeigen, müssen wir sie zunächst aus dem lokalen Speicher abrufen. Dazu verwenden wir die Methode JSON.parse(), mit der die Zeichenfolgen wieder in JavaScript-Objekte konvertiert werden.

Als Nächstes speichern wir alle Aufgaben im vertrauten tasks-Array. Beachten Sie, dass dieses Array leer ist, wenn sich keine Daten im lokalen Speicher befinden (z. B. beim ersten Besuch der App). Dann müssen wir das Array durchlaufen und für jede Aufgabe die Funktion createTask() aufrufen. Und das ist alles!

Das entsprechende Code-Snippet:

Schlussfolgerung

Puh! Vielen Dank, dass Sie diese lange Reise mitgemacht haben. Hoffentlich haben Sie heute einige neue Kenntnisse gewonnen, die Sie auf Ihre eigenen Projekte anwenden können.

Erinnern wir uns daran, was wir gebaut haben:

Ohne Zweifel ist das Erstellen einer solchen App mit einem JavaScript-Framework möglicherweise stabiler, einfacher und effizienter (das Neulackieren des DOM ist teuer). Wenn Sie jedoch wissen, wie Sie diese Art von Übung mit einfachem JavaScript lösen können, erhalten Sie einen soliden Überblick über die Grundlagen und werden zu einem besseren JavaScript-Entwickler.

Lassen Sie mich vor dem Abschluss zwei Ideen zur Erweiterung dieser Übung vorschlagen:

  • Verwenden Sie die HTML-Drag & Drop-API oder eine JavaScript-Bibliothek wie Sortable.js, um die Aufgaben neu zu ordnen.
  • Speichern Sie Daten(Aufgaben) in der Cloud anstelle des Browsers. Ersetzen Sie beispielsweise den lokalen Speicher durch eine Echtzeitdatenbank wie Firebase.

Wie immer vielen Dank fürs Lesen!

Weitere Vanilla JavaScript Apps

Wenn Sie lernen möchten, wie Sie kleine Apps mit einfachem JavaScript erstellen, lesen Sie die folgenden Tutorials:

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.