You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/de/7-bank-project/3-data
localizeflow[bot] 1936fdd40c
chore(i18n): sync translations with latest source changes (chunk 10/21, 100 files)
1 month ago
..
README.md chore(i18n): sync translations with latest source changes (chunk 10/21, 100 files) 1 month ago
assignment.md chore(i18n): sync translations with latest source changes (chunk 10/21, 100 files) 1 month ago

README.md

Erstellen Sie eine Banking-App Teil 3: Methoden zum Abrufen und Verwenden von Daten

Denken Sie an den Computer der Enterprise in Star Trek wenn Captain Picard nach dem Status des Schiffs fragt, erscheinen die Informationen sofort, ohne dass die gesamte Benutzeroberfläche herunterfährt und sich neu aufbaut. Dieser nahtlose Informationsfluss ist genau das, was wir hier mit dynamischem Datenabruf aufbauen.

Im Moment ist Ihre Banking-App wie eine gedruckte Zeitung informativ, aber statisch. Wir werden sie in etwas verwandeln, das eher wie die Missionskontrolle bei der NASA ist, wo Daten kontinuierlich fließen und sich in Echtzeit aktualisieren, ohne den Arbeitsablauf des Nutzers zu unterbrechen.

Sie lernen, wie Sie asynchron mit Servern kommunizieren, Daten verarbeiten, die zu unterschiedlichen Zeiten eintreffen, und rohe Informationen in etwas Bedeutungsvolles für Ihre Nutzer verwandeln. Das ist der Unterschied zwischen einer Demo und produktionsbereiter Software.

Was Sie in den nächsten 5 Minuten tun können

Schnellstart-Pfad für beschäftigte Entwickler

flowchart LR
    A[⚡ 5 Minuten] --> B[API-Server einrichten]
    B --> C[Test Abruf mit curl]
    C --> D[Login-Funktion erstellen]
    D --> E[Daten in Aktion sehen]
  • Minute 1-2: Starten Sie Ihren API-Server (cd api && npm start) und testen Sie die Verbindung
  • Minute 3: Erstellen Sie eine grundlegende getAccount()-Funktion mit fetch
  • Minute 4: Verbinden Sie das Login-Formular mit action="javascript:login()"
  • Minute 5: Testen Sie das Login und beobachten Sie, wie Kontodaten in der Konsole erscheinen

Schnelltest-Befehle:

# Überprüfen, ob die API läuft
curl http://localhost:5000/api

# Testen des Abrufs von Kontodaten
curl http://localhost:5000/api/accounts/test

Warum das wichtig ist: In 5 Minuten erleben Sie die Magie des asynchronen Datenabrufs, der jede moderne Webanwendung antreibt. Das ist die Grundlage, die Apps reaktionsschnell und lebendig wirken lässt.

🗺️ Ihre Lernreise durch datengetriebene Webanwendungen

journey
    title Von statischen Seiten zu dynamischen Anwendungen
    section Die Entwicklung verstehen
      Traditionelle Seitenaktualisierungen: 3: You
      Vorteile von AJAX/SPA entdecken: 5: You
      Fetch API-Muster meistern: 7: You
    section Authentifizierung aufbauen
      Login-Funktionen erstellen: 4: You
      Asynchrone Operationen handhaben: 6: You
      Benutzersitzungen verwalten: 8: You
    section Dynamische UI-Aktualisierungen
      DOM-Manipulation lernen: 5: You
      Transaktionsanzeigen erstellen: 7: You
      Reaktionsfähige Dashboards erstellen: 9: You
    section Professionelle Muster
      Template-basierte Darstellung: 6: You
      Strategien zur Fehlerbehandlung: 7: You
      Leistungsoptimierung: 8: You

Ihr Lernziel: Am Ende dieser Lektion verstehen Sie, wie moderne Webanwendungen Daten dynamisch abrufen, verarbeiten und anzeigen, um die nahtlosen Benutzererlebnisse zu schaffen, die wir von professionellen Anwendungen erwarten.

Vorbereitendes Quiz

Vorbereitendes Quiz

Voraussetzungen

Bevor Sie mit dem Datenabruf beginnen, stellen Sie sicher, dass Sie diese Komponenten bereithalten:

curl http://localhost:5000/api
# Erwartete Antwort: "Bank API v1.0.0"

Dieser Schnelltest stellt sicher, dass alle Komponenten richtig kommunizieren:

  • Verifiziert, dass Node.js auf Ihrem System korrekt läuft
  • Bestätigt, dass Ihr API-Server aktiv und antwortfähig ist
  • Validiert, dass Ihre App den Server erreichen kann (wie Funkkontakt vor einer Mission prüfen)

🧠 Überblick über das Datenmanagement-Ökosystem

mindmap
  root((Datenverwaltung))
    Authentication Flow
      Anmeldevorgang
        Formularvalidierung
        Anmeldeinformationen Überprüfung
        Sitzungsverwaltung
      Benutzerzustand
        Globales Kontoobjekt
        Navigationsschutz
        Fehlerbehandlung
    API Communication
      Abrufmuster
        GET-Anfragen
        POST-Anfragen
        Fehlerantworten
      Datenformate
        JSON-Verarbeitung
        URL-Kodierung
        Antwortparsing
    Dynamic UI Updates
      DOM-Manipulation
        Sichere Textaktualisierungen
        Elementerstellung
        Vorlagenklonen
      Benutzererlebnis
        Echtzeitaktualisierungen
        Fehlermeldungen
        Ladezustände
    Security Considerations
      XSS-Vermeidung
        Verwendung von textContent
        Eingabesäuberung
        Sichere HTML-Erstellung
      CORS-Verarbeitung
        Cross-Origin-Anfragen
        Header-Konfiguration
        Entwicklungssetup

Grundprinzip: Moderne Webanwendungen sind Datenorchestrierungssysteme sie koordinieren zwischen Benutzeroberflächen, Server-APIs und dem Sicherheitsmodell des Browsers, um nahtlose, reaktionsschnelle Erlebnisse zu schaffen.


Verständnis des Datenabrufs in modernen Web-Apps

Die Art und Weise, wie Webanwendungen Daten verarbeiten, hat sich in den letzten zwei Jahrzehnten dramatisch entwickelt. Dieses Verständnis hilft Ihnen zu schätzen, warum moderne Techniken wie AJAX und die Fetch API so mächtig sind und warum sie zu unverzichtbaren Werkzeugen für Webentwickler geworden sind.

Lassen Sie uns erkunden, wie traditionelle Webseiten funktionierten im Vergleich zu den dynamischen, reaktionsschnellen Anwendungen, die wir heute bauen.

Traditionelle Mehrseitenanwendungen (MPA)

In den frühen Tagen des Webs war jeder Klick wie das Umschalten auf einem alten Fernseher der Bildschirm wurde leer, dann wurde der neue Inhalt langsam geladen. Dies war die Realität bei frühen Webanwendungen, bei denen jede Interaktion bedeutete, die gesamte Seite komplett neu aufzubauen.

sequenceDiagram
    participant User
    participant Browser
    participant Server
    
    User->>Browser: Klickt auf Link oder sendet Formular ab
    Browser->>Server: Fordert neue HTML-Seite an
    Note over Browser: Seite wird leer
    Server->>Browser: Gibt komplette HTML-Seite zurück
    Browser->>User: Zeigt neue Seite an (Blitz/Neuladen)

Aktualisierungsworkflow in einer Mehrseitenanwendung

Warum sich dieser Ansatz schwerfällig anfühlte:

  • Jeder Klick bedeutete, die gesamte Seite neu zu laden
  • Nutzer wurden mitten im Gedankenfluss durch diese lästigen Seitenflashes unterbrochen
  • Ihre Internetverbindung arbeitete übermäßig, da dieselben Kopf- und Fußzeilen immer wieder heruntergeladen wurden
  • Apps fühlten sich eher an wie das Durchklicken in einem Aktenschrank als wie Software

Moderne Single-Page-Anwendungen (SPA)

AJAX (Asynchronous JavaScript and XML) hat dieses Paradigma komplett verändert. Wie das modulare Design der Internationalen Raumstation, bei dem Astronauten einzelne Komponenten austauschen können, ohne die ganze Struktur neu zu bauen, erlaubt AJAX uns, spezifische Teile einer Webseite zu aktualisieren, ohne alles neu zu laden. Obwohl der Name XML erwähnt, verwenden wir heute meist JSON, aber das Grundprinzip bleibt: Nur das aktualisieren, was sich ändert.

sequenceDiagram
    participant User
    participant Browser
    participant JavaScript
    participant Server
    
    User->>Browser: Interagiert mit Seite
    Browser->>JavaScript: Löst Ereignis-Handler aus
    JavaScript->>Server: Ruft nur benötigte Daten ab
    Server->>JavaScript: Gibt JSON-Daten zurück
    JavaScript->>Browser: Aktualisiert spezifische Seitenelemente
    Browser->>User: Zeigt aktualisierten Inhalt (kein Neuladen)

Aktualisierungsworkflow in einer Single-Page-Anwendung

Warum SPAs sich so viel besser anfühlen:

  • Nur die tatsächlich geänderten Bereiche werden aktualisiert (clever, oder?)
  • Keine ruckartigen Unterbrechungen mehr Ihre Nutzer bleiben im Flow
  • Weniger Daten werden übertragen, was schnellere Ladezeiten bedeutet
  • Alles wirkt flink und reaktionsschnell, wie die Apps auf Ihrem Smartphone

Die Entwicklung zur modernen Fetch API

Moderne Browser bieten die Fetch API, die den älteren XMLHttpRequest ersetzt. Wie der Unterschied zwischen Telegrafbedienung und E-Mail-Nutzung verwendet die Fetch API Promises für saubereren asynchronen Code und verarbeitet JSON auf natürliche Weise.

Merkmal XMLHttpRequest Fetch API
Syntax Komplex, callback-basiert Sauber, promise-basiert
JSON-Verarbeitung Manuelle Verarbeitung erforderlich Eingebaute .json()-Methode
Fehlerbehandlung Begrenzte Fehlerinformationen Umfangreiche Fehlerdetails
Moderne Unterstützung Kompatibilität mit alten Browsern ES6+ Promises und async/await

💡 Browser-Kompatibilität: Gute Nachrichten die Fetch API funktioniert in allen modernen Browsern! Wenn Sie an bestimmten Versionen interessiert sind, bietet caniuse.com die vollständige Kompatibilitätsübersicht.

Das Fazit:

  • Funktioniert hervorragend in Chrome, Firefox, Safari und Edge (ganz einfach überall dort, wo Ihre Nutzer sind)
  • Nur Internet Explorer benötigt spezielle Unterstützung (und ehrlich gesagt, es ist Zeit, IE loszulassen)
  • Bereitet Sie bestens auf die eleganten async/await-Patterns vor, die wir später verwenden werden

Implementierung von Nutzer-Login und Datenabruf

Nun implementieren wir das Login-System, das Ihre Banking-App von einer statischen Anzeige zu einer funktionalen Anwendung macht. Wie bei den Authentifizierungsprotokollen in sicheren Militäranlagen verifizieren wir Nutzeranmeldeinformationen und gewähren dann Zugriff auf die spezifischen Daten.

Wir bauen dies schrittweise auf, beginnend mit der Basisauthentifizierung und dann der Ergänzung um Datenabruffunktionen.

Schritt 1: Erstellen der Login-Funktionsbasis

Öffnen Sie Ihre app.js und fügen Sie eine neue login-Funktion hinzu. Diese verarbeitet den Nutzer-Authentifizierungsprozess:

async function login() {
  const loginForm = document.getElementById('loginForm');
  const user = loginForm.user.value;
}

So funktioniert das im Detail:

  • Das async Schlüsselwort sagt JavaScript „hey, diese Funktion könnte auf Dinge warten müssen“
  • Wir greifen auf unser Formular der Seite zu (nichts Besonderes, einfach per ID)
  • Dann holen wir raus, was der Nutzer als Benutzernamen eingegeben hat
  • Ein cooler Trick: Sie können auf jedes Formularelement durch dessen name-Attribut zugreifen keine extra getElementById-Aufrufe nötig!

💡 Formularzugriffsmuster: Jede Formulareingabe kann über ihren Namen (festgelegt im HTML mit dem name-Attribut) als Eigenschaft des Formular-Elements angesprochen werden. Das sorgt für sauberen, lesbaren Code beim Abrufen der Formulardaten.

Schritt 2: Erstellen der Konto-Datenabruf-Funktion

Als Nächstes erstellen wir eine dedizierte Funktion, um Kontodaten vom Server abzurufen. Dieses Muster ist ähnlich wie bei Ihrer Registrierungsfunktion, konzentriert sich aber auf das Abrufen von Daten:

async function getAccount(user) {
  try {
    const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user));
    return await response.json();
  } catch (error) {
    return { error: error.message || 'Unknown error' };
  }
}

Was dieser Code leistet:

  • Verwendet die moderne fetch API für asynchronen Datenabruf
  • Erstellt eine GET-Anfrage-URL mit dem Benutzernamen als Parameter
  • Setzt encodeURIComponent() ein, um Sonderzeichen in URLs sicher zu handhaben
  • Konvertiert die Antwort in JSON-Format für einfache Datenverarbeitung
  • Behandelt Fehler elegant, indem ein Fehlerobjekt zurückgegeben wird, anstatt abzustürzen

⚠️ Sicherheitshinweis: Die Funktion encodeURIComponent() behandelt Sonderzeichen in URLs. Wie bei Kodierungssystemen in der Marine sorgt sie dafür, dass Ihre Nachricht genau so ankommt, wie vorgesehen, und verhindert, dass Zeichen wie "#" oder "&" fehlinterpretiert werden.

Warum das wichtig ist:

  • Verhindert, dass Sonderzeichen URLs zerstören
  • Schützt vor URL-Manipulationsangriffen
  • Stellt sicher, dass Ihr Server die vorgesehenen Daten erhält
  • Folgt sicheren Programmierpraktiken

Verständnis von HTTP GET-Anfragen

Hier etwas, was Sie vielleicht überrascht: Wenn Sie fetch ohne zusätzliche Optionen verwenden, erzeugt es automatisch eine GET-Anfrage. Das passt perfekt zu unserem Zweck wir fragen den Server „hey, kann ich die Kontodaten dieses Nutzers sehen?“

Stellen Sie sich GET-Anfragen vor wie eine höfliche Bibliotheksanfrage, ein Buch auszuleihen Sie bitten darum, etwas zu sehen, das bereits existiert. POST-Anfragen (wie bei der Registrierung) sind eher wie das Einreichen eines neuen Buches, das in die Sammlung aufgenommen werden soll.

GET-Anfrage POST-Anfrage
Zweck Vorhandene Daten abrufen
Parameter In URL-Pfad/Abfragezeichenfolge
Caching Kann von Browsern zwischengespeichert werden
Sicherheit Sichtbar in URL/Logs
sequenceDiagram
    participant B as Browser
    participant S as Server
    
    Note over B,S: GET-Anfrage (Datenabruf)
    B->>S: GET /api/accounts/test
    S-->>B: 200 OK + Kontodaten
    
    Note over B,S: POST-Anfrage (Datenübermittlung)
    B->>S: POST /api/accounts + Neue Kontodaten
    S-->>B: 201 Created + Bestätigung
    
    Note over B,S: Fehlerbehandlung
    B->>S: GET /api/accounts/nonexistent
    S-->>B: 404 Not Found + Fehlermeldung

Schritt 3: Alles zusammenführen

Jetzt zum befriedigenden Teil wir verbinden Ihre Kontodaten-Abruf-Funktion mit dem Login-Prozess. Hier fügt sich alles zusammen:

async function login() {
  const loginForm = document.getElementById('loginForm');
  const user = loginForm.user.value;
  const data = await getAccount(user);

  if (data.error) {
    return console.log('loginError', data.error);
  }

  account = data;
  navigate('/dashboard');
}

Diese Funktion folgt einer klaren Abfolge:

  • Den Benutzernamen aus dem Formulareingabefeld extrahieren
  • Kontodaten vom Server für den Nutzer anfordern
  • Etwaige Fehler während des Prozesses behandeln
  • Kontodaten speichern und nach erfolgreichem Login zum Dashboard navigieren

🎯 Async/Await-Muster: Da getAccount asynchron ist, verwenden wir das await-Schlüsselwort, um die Ausführung zu pausieren, bis der Server antwortet. Das verhindert, dass der Code mit undefinierten Daten weiterläuft.

Schritt 4: Einen Speicherort für Ihre Daten schaffen

Ihre App benötigt einen Ort, um die Kontoinformationen zu speichern, sobald sie geladen sind. Stellen Sie sich das wie das Kurzzeitgedächtnis Ihrer App vor ein Platz, um die aktuellen Nutzerdaten griffbereit zu halten. Fügen Sie folgende Zeile ganz oben in Ihre app.js ein:

// Dies enthält die Kontodaten des aktuellen Benutzers
let account = null;

Warum wir das brauchen:

  • Macht Kontodaten überall in der App zugänglich
  • Startet mit null, was bedeutet: „niemand ist eingeloggt“
  • Wird aktualisiert, wenn jemand erfolgreich anmeldet oder sich registriert
  • Dient als einzige wahre Datenquelle keine Verwirrung darüber, wer gerade eingeloggt ist

Schritt 5: Formular verbinden

Nun verbinden wir Ihre nagelneue Login-Funktion mit Ihrem HTML-Formular. Aktualisieren Sie das Formular-Tag so:

<form id="loginForm" action="javascript:login()">
  <!-- Your existing form inputs -->
</form>

Was diese kleine Änderung bewirkt:

  • Verhindert, dass das Formular seine Standardaktion „Seite neu laden“ ausführt
  • Ruft stattdessen Ihre benutzerdefinierte JavaScript-Funktion auf
  • Hält alles flüssig und spa-ähnlich
  • Gibt Ihnen die volle Kontrolle darüber, was beim Klick auf „Login“ passiert

Schritt 6: Registrierungsfunktion erweitern

Zur Konsistenz aktualisieren Sie Ihre register-Funktion ebenfalls, sodass sie Kontodaten speichert und zum Dashboard navigiert:

// Fügen Sie diese Zeilen am Ende Ihrer Registrierungsfunktion hinzu
account = result;
navigate('/dashboard');

Diese Verbesserung bietet:

  • Nahtlosen Übergang von der Registrierung zum Dashboard
  • Konsistentes Nutzererlebnis bei Login und Registrierung
  • Sofortigen Zugriff auf Kontodaten nach erfolgreicher Registrierung

Testen Sie Ihre Implementierung

flowchart TD
    A[Benutzer gibt Zugangsdaten ein] --> B[Login-Funktion aufgerufen]
    B --> C[Kontodaten vom Server abrufen]
    C --> D{Daten erfolgreich empfangen?}
    D -->|Ja| E[Kontodaten global speichern]
    D -->|Nein| F[Fehlermeldung anzeigen]
    E --> G[Zum Dashboard navigieren]
    F --> H[Benutzer bleibt auf der Login-Seite]

Zeit für den Praxistest:

  1. Legen Sie ein neues Konto an, um sicherzugehen, dass alles funktioniert
  2. Versuchen Sie, sich mit diesen Daten einzuloggen
  3. Werfen Sie einen Blick in die Browser-Konsole (F12), wenn etwas komisch erscheint
  4. Überprüfen Sie, ob Sie nach erfolgreichem Login auf dem Dashboard landen

Wenn etwas nicht funktioniert, keine Panik! Die meisten Probleme sind einfache Fehler wie Tippfehler oder vergessen, den API-Server zu starten.

Ein kurzes Wort zur Cross-Origin-Magie

Vielleicht fragen Sie sich: „Wie kommuniziert meine Web-App mit diesem API-Server, wenn sie auf unterschiedlichen Ports laufen?“ Gute Frage! Das ist etwas, worauf jeder Webentwickler früher oder später stößt.

🔒 Cross-Origin-Sicherheit: Browser erzwingen eine „Same-Origin-Policy“, um unautorisierte Kommunikation zwischen verschiedenen Domains zu verhindern. Wie ein Kontrollpunkt im Pentagon prüfen sie, ob die Kommunikation erlaubt ist, bevor Daten übertragen werden.

In unserem Setup:

  • Läuft Ihre Web-App auf localhost:3000 (Entwicklungsserver)
  • Läuft Ihr API-Server auf localhost:5000 (Backend-Server)
  • Der API-Server enthält CORS-Header, die explizit die Kommunikation mit Ihrer Web-App erlauben

Diese Konfiguration entspricht der realen Entwicklung, bei der Frontend- und Backend-Anwendungen meist auf getrennten Servern laufen.

📚 Mehr erfahren: Tauchen Sie tiefer in APIs und Datenabruf ein mit diesem umfassenden Microsoft Learn-Modul zu APIs.

Ihre Daten durch HTML zum Leben erwecken

Jetzt machen wir die abgerufenen Daten für Nutzer über DOM-Manipulation sichtbar. Wie im analogen Fotolabor entwickeln wir unsichtbare Daten zu etwas, das Nutzer sehen und mit dem sie interagieren können. DOM-Manipulation ist die Technik, die statische Webseiten in dynamische Anwendungen verwandelt, die ihre Inhalte basierend auf Benutzerinteraktionen und Serverantworten aktualisieren.

Die richtige Werkzeugwahl für den Job

Wenn es darum geht, dein HTML mit JavaScript zu aktualisieren, hast du mehrere Optionen. Denk an diese wie verschiedene Werkzeuge in einem Werkzeugkasten jedes perfekt für bestimmte Aufgaben:

Methode Wofür sie großartig ist Wann man sie benutzt Sicherheitsstufe
textContent Sichere Anzeige von Benutzerdaten Immer wenn du Text anzeigen willst Felsenfest
createElement() + append() Aufbau komplexer Layouts Neue Abschnitte/Listen erstellen Bombensicher
innerHTML Setzen von HTML-Inhalten ⚠️ Versuche, diese Methode zu vermeiden Risikohaft

Der sichere Weg, Text anzuzeigen: textContent

Die textContent-Eigenschaft ist dein bester Freund, wenn es darum geht, Benutzerdaten anzuzeigen. Es ist, als hättest du einen Türsteher für deine Webseite nichts Gefährliches kommt durch:

// Der sichere, zuverlässige Weg, Text zu aktualisieren
const balanceElement = document.getElementById('balance');
balanceElement.textContent = account.balance;

Vorteile von textContent:

  • Behandelt alles als reinen Text (verhindert die Ausführung von Skripten)
  • Löscht automatisch vorhandenen Inhalt
  • Effizient für einfache Textupdates
  • Bietet integrierten Schutz gegen bösartigen Inhalt

Dynamische HTML-Elemente erstellen

Für komplexere Inhalte kombiniere document.createElement() mit der append()-Methode:

// Sicherer Weg, um neue Elemente zu erstellen
const transactionItem = document.createElement('div');
transactionItem.className = 'transaction-item';
transactionItem.textContent = `${transaction.date}: ${transaction.description}`;
container.append(transactionItem);

So funktioniert dieser Ansatz:

  • Erstellt DOM-Elemente programmgesteuert neu
  • Behält volle Kontrolle über Elementattribute und Inhalte
  • Ermöglicht komplexe, verschachtelte Elementstrukturen
  • Bewahrt die Sicherheit, indem Struktur von Inhalt getrennt wird

⚠️ Sicherheitsbedenken: Obwohl innerHTML in vielen Tutorials auftaucht, kann es eingebettete Skripte ausführen. Wie die Sicherheitsprotokolle am CERN, die unbefugte Codeausführung verhindern, bieten textContent und createElement sicherere Alternativen.

Risiken von innerHTML:

  • Führt jegliche <script>-Tags in Benutzerdaten aus
  • Anfällig für Code-Injection-Angriffe
  • Erzeugt mögliche Sicherheitslücken
  • Die sichereren Alternativen bieten die gleiche Funktionalität

Fehler benutzerfreundlich machen

Derzeit erscheinen Login-Fehler nur in der Browser-Konsole, die für Benutzer unsichtbar ist. Wie der Unterschied zwischen den internen Diagnosen eines Piloten und dem Passagierinformationssystem müssen wir wichtige Informationen über den passenden Kanal kommunizieren.

Sichtbare Fehlermeldungen geben den Benutzern sofortiges Feedback darüber, was schiefgelaufen ist und wie sie vorgehen sollten.

Schritt 1: Einen Platz für Fehlermeldungen hinzufügen

Zuerst geben wir den Fehlermeldungen einen Platz in deinem HTML. Füge dies direkt vor deinem Login-Button hinzu, damit die Benutzer es natürlich sehen:

<!-- This is where error messages will appear -->
<div id="loginError" role="alert"></div>
<button>Login</button>

Was hier passiert:

  • Wir erstellen einen leeren Container, der unsichtbar bleibt, bis er gebraucht wird
  • Er ist dort positioniert, wo Benutzer nach dem Klicken auf "Login" natürlich hinschauen
  • Das role="alert" ist ein netter Bonus für Screenreader es signalisiert unterstützenden Technologien „Achtung, wichtig!“
  • Die eindeutige id gibt unserem JavaScript ein leicht zu findendes Ziel

Schritt 2: Eine praktische Helferfunktion erstellen

Lass uns eine kleine Hilfsfunktion schreiben, die den Text eines beliebigen Elements aktualisiert. Eine dieser "einmal schreiben, überall nutzen" Funktionen, die dir Zeit spart:

function updateElement(id, text) {
  const element = document.getElementById(id);
  element.textContent = text;
}

Vorteile der Funktion:

  • Einfache Schnittstelle, die nur eine Element-ID und Textinhalt benötigt
  • Sucht und aktualisiert DOM-Elemente sicher
  • Wiederverwendbares Muster, das Code-Duplizierung verringert
  • Sorgt für einheitliches Update-Verhalten in der Anwendung

Schritt 3: Fehler dort anzeigen, wo Benutzer sie sehen können

Jetzt ersetzen wir die versteckte Konsolenmeldung durch eine Nachricht, die Benutzer tatsächlich sehen. Aktualisiere deine Login-Funktion:

// Anstatt nur in der Konsole zu protokollieren, zeigen Sie dem Benutzer, was falsch ist
if (data.error) {
  return updateElement('loginError', data.error);
}

Diese kleine Änderung bewirkt viel:

  • Fehlermeldungen erscheinen genau dort, wo Benutzer hinschauen
  • Keine mysteriösen, stillen Fehler mehr
  • Benutzer erhalten sofortiges, umsetzbares Feedback
  • Deine App wirkt professionell und durchdacht

Wenn du jetzt mit einem ungültigen Konto testest, siehst du eine hilfreiche Fehlermeldung direkt auf der Seite!

Screenshot zeigt die während des Logins angezeigte Fehlermeldung

Schritt 4: Zugänglichkeit und Inklusion fördern

Etwas Cooles an dem role="alert", das wir eben hinzugefügt haben es ist nicht nur Dekoration! Dieses kleine Attribut erstellt eine sogenannte Live Region, die Änderungen sofort für Screenreader ansagt:

<div id="loginError" role="alert"></div>

Warum das wichtig ist:

  • Screenreader-Benutzer hören die Fehlermeldung sofort nach ihrem Erscheinen
  • Alle erhalten dieselbe wichtige Information, egal wie sie navigieren
  • Ein einfacher Weg, damit deine App für mehr Menschen funktioniert
  • Zeigt, dass dir inklusive Erlebnisse wichtig sind

Solche kleinen Details trennen gute Entwickler von großartigen!

🎯 Pädagogische Zwischenfrage: Authentifizierungsmuster

Pause und Reflexion: Du hast gerade einen kompletten Authentifizierungsablauf implementiert. Dies ist ein grundlegendes Muster in der Webentwicklung.

Kurze Selbstbewertung:

  • Kannst du erklären, warum wir für API-Aufrufe async/await verwenden?
  • Was passiert, wenn wir die Funktion encodeURIComponent() vergessen?
  • Wie verbessert unsere Fehlerbehandlung die Benutzererfahrung?

Verbindung zur Praxis: Die Muster, die du hier gelernt hast (asynchrone Datenabfrage, Fehlerbehandlung, Benutzerfeedback), werden in jeder großen Webanwendung verwendet, von sozialen Netzwerken bis zu E-Commerce-Seiten. Du entwickelst Produktionsfähigkeiten!

Herausforderungsfrage: Wie könntest du dieses Authentifizierungssystem ändern, damit mehrere Benutzerrollen (Kunde, Administrator, Kassierer) unterstützt werden? Denke über Datenstruktur und UI-Änderungen nach.

Schritt 5: Dasselbe Muster für die Registrierung anwenden

Für Konsistenz implementiere eine identische Fehlerbehandlung in deinem Registrierungsformular:

  1. Füge ein Fehleranzeigeelement zu deinem Registrierungs-HTML hinzu:
<div id="registerError" role="alert"></div>
  1. Aktualisiere deine Registrierung-Funktion, um das gleiche Fehleranzeigen-Muster zu nutzen:
if (data.error) {
  return updateElement('registerError', data.error);
}

Vorteile einer einheitlichen Fehlerbehandlung:

  • Bietet eine konsistente Benutzererfahrung in allen Formularen
  • Verringert die kognitive Belastung durch vertraute Muster
  • Vereinfacht Wartung durch wiederverwendbaren Code
  • Stellt sicher, dass die Zugänglichkeitsstandards in der gesamten App eingehalten werden

Erstellung deines dynamischen Dashboards

Jetzt verwandeln wir dein statisches Dashboard in eine dynamische Oberfläche, die echte Kontodaten anzeigt. Wie der Unterschied zwischen einem gedruckten Flugplan und den Live-Abflugtafeln am Flughafen wechseln wir von statischen Infos zu Echtzeit-aktualisierten Anzeigen.

Mit den DOM-Manipulations-Techniken, die du gelernt hast, erstellen wir ein Dashboard, das sich automatisch mit den aktuellen Kontoinformationen aktualisiert.

Deine Daten kennenlernen

Bevor wir mit dem Bauen beginnen, werfen wir einen Blick darauf, welche Daten dein Server zurückschickt. Wenn sich jemand erfolgreich anmeldet, erhältst du diesen Schatz an Informationen:

{
  "user": "test",
  "currency": "$",
  "description": "Test account",
  "balance": 75,
  "transactions": [
    { "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
    { "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
    { "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
  ]
}

Diese Datenstruktur liefert:

  • user: Perfekt zur Personalisierung des Erlebnisses ("Willkommen zurück, Sarah!")
  • currency: Damit Beträge korrekt angezeigt werden
  • description: Ein freundlicher Name für das Konto
  • balance: Der wichtige aktuelle Kontostand
  • transactions: Die komplette Transaktionshistorie mit allen Details

Alles, was du brauchst, um ein professionelles Banking-Dashboard zu bauen!

flowchart TD
    A[Benutzeranmeldung] --> B[Kontodaten abrufen]
    B --> C{Daten gültig?}
    C -->|Ja| D[In globale Variable speichern]
    C -->|Nein| E[Fehlermeldung anzeigen]
    D --> F[Zum Dashboard navigieren]
    F --> G[UI-Elemente aktualisieren]
    G --> H[Saldo anzeigen]
    G --> I[Beschreibung anzeigen]
    G --> J[Transaktionen anzeigen]
    J --> K[Tabelle Zeilen erstellen]
    K --> L[Währung formatieren]
    L --> M[Benutzer sieht Live-Daten]

💡 Profi-Tipp: Möchtest du dein Dashboard sofort in Aktion sehen? Verwende den Benutzernamen test beim Einloggen dieses Konto ist mit Beispieldaten vorinstalliert, damit du ohne vorherige Transaktion alles in Aktion sehen kannst.

Warum das Testkonto praktisch ist:

  • Hat realistische Beispieldaten vorab geladen
  • Perfekt, um zu sehen, wie Transaktionen dargestellt werden
  • Ideal zum Testen deiner Dashboard-Funktionalität
  • Spart dir das manuelle Erstellen von Dummy-Daten

Erstellung der Dashboard-Anzeigeelemente

Bauen wir deine Dashboard-Oberfläche Schritt für Schritt auf, angefangen mit der Kontenübersicht und später mit komplexeren Features wie Transaktionslisten.

Schritt 1: Aktualisiere deine HTML-Struktur

Zuerst ersetzt du den statischen "Saldo"-Bereich durch dynamische Platzhalter-Elemente, die dein JavaScript befüllen kann:

<section>
  Balance: <span id="balance"></span><span id="currency"></span>
</section>

Füge anschließend einen Bereich für die Kontobeschreibung hinzu. Da dies als Titel für den Dashboard-Inhalt dient, verwende semantisches HTML:

<h2 id="description"></h2>

Verständnis der HTML-Struktur:

  • Verwendet separate <span>-Elemente für Saldo und Währung, um individuelle Kontrolle zu ermöglichen
  • Vergibt eindeutige IDs für jedes Element, die JavaScript anvisieren kann
  • Nutzt semantisches HTML durch <h2> für die Kontobeschreibung
  • Schafft eine logische Hierarchie für Screenreader und SEO

Zugänglichkeits-Tipp: Die Kontobeschreibung fungiert als Titel des Dashboard-Inhalts, daher ist sie semantisch als Überschrift ausgezeichnet. Erfahre mehr darüber, wie Überschriftenstruktur die Zugänglichkeit verbessert. Kannst du weitere Elemente auf deiner Seite finden, die von Überschriften profitieren könnten?

Schritt 2: Erstelle die Dashboard-Aktualisierungsfunktion

Erstelle nun eine Funktion, die dein Dashboard mit echten Kontodaten befüllt:

function updateDashboard() {
  if (!account) {
    return navigate('/login');
  }

  updateElement('description', account.description);
  updateElement('balance', account.balance.toFixed(2));
  updateElement('currency', account.currency);
}

Schritt für Schritt erklärt macht diese Funktion:

  • Prüft, ob Kontodaten vorhanden sind, bevor sie fortfährt
  • Leitet nicht authentifizierte Benutzer zurück zur Login-Seite
  • Aktualisiert die Kontobeschreibung mit der wiederverwendbaren updateElement-Funktion
  • Formatiert den Saldo so, dass immer zwei Nachkommastellen angezeigt werden
  • Zeigt das passende Währungssymbol an

💰 Geldformatierung: Die Methode toFixed(2) ist ein echter Retter! Sie stellt sicher, dass dein Saldo immer wie echtes Geld aussieht "75.00" statt nur "75". Deine Benutzer werden geschätztes, vertrautes Währungsformat sehen.

Schritt 3: Sicherstellen, dass dein Dashboard aktualisiert wird

Damit dein Dashboard bei jedem Besuch mit aktuellen Daten lädt, müssen wir es in dein Navigationssystem einbinden. Wenn du die Aufgabe aus Lektion 1 abgeschlossen hast, kommt dir das bekannt vor. Wenn nicht, keine Sorge das brauchst du:

Füge dies ans Ende deiner updateRoute()-Funktion hinzu:

if (typeof route.init === 'function') {
  route.init();
}

Dann aktualisiere deine Routen, um die Dashboard-Initialisierung einzubinden:

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard', init: updateDashboard }
};

Was diese clevere Einrichtung macht:

  • Prüft, ob eine Route speziellen Initialisierungscode hat
  • Führt diesen Code automatisch aus, wenn die Route geladen wird
  • Sorgt dafür, dass dein Dashboard immer frische, aktuelle Daten zeigt
  • Hält deine Routing-Logik sauber und organisiert

Dashboard testen

Teste nach der Implementierung diese Punkte:

  1. Melde dich mit einem Testkonto an
  2. Vergewissere dich, dass du zum Dashboard weitergeleitet wirst
  3. Prüfe, ob Kontobeschreibung, Saldo und Währung korrekt angezeigt werden
  4. Melde dich ab und wieder an, um sicherzustellen, dass die Daten richtig aktualisiert werden

Dein Dashboard sollte jetzt dynamische Kontoinformationen anzeigen, die auf den angemeldeten Benutzer zugeschnitten sind!

Intelligente Transaktionslisten mit Templates erstellen

Anstatt HTML für jede Transaktion manuell zu erstellen, verwenden wir Templates, um automatisch einheitliches Format zu erzeugen. Wie standardisierte Bauteile in der Raumfahrtfertigung sorgen Templates dafür, dass jede Transaktionszeile der gleichen Struktur und Darstellung folgt.

Diese Technik skaliert effizient von wenigen bis zu tausenden Transaktionen und garantiert konstante Performance und Layoutqualität.

graph LR
    A[HTML Vorlage] --> B[JavaScript Klon]
    B --> C[Mit Daten füllen]
    C --> D[Zum Fragment hinzufügen]
    D --> E[Batch-Einfügung in DOM]
    
    subgraph "Leistungs-Vorteile"
        F[Einzelnes DOM-Update]
        G[Konsistentes Formatieren]
        H[Wiederverwendbares Muster]
    end
    
    E --> F
    E --> G
    E --> H
flowchart LR
    A[Transaktionsdaten] --> B[HTML-Vorlage]
    B --> C[Vorlage klonen]
    C --> D[Mit Daten füllen]
    D --> E[Zum DOM hinzufügen]
    E --> F[Für jede Transaktion wiederholen]

Schritt 1: Erstelle das Transaktions-Template

Füge zuerst ein wiederverwendbares Template für Transaktionszeilen innerhalb des <body> deiner HTML-Datei hinzu:

<template id="transaction">
  <tr>
    <td></td>
    <td></td>
    <td></td>
  </tr>
</template>

Verständnis von HTML-Templates:

  • Definiert die Struktur für eine einzelne Tabellenzeile
  • Bleibt unsichtbar, bis es geklont und mit JavaScript befüllt wird
  • Beinhaltet drei Zellen für Datum, Beschreibung und Betrag
  • Bietet ein wiederverwendbares Muster für konsistente Formatierung

Schritt 2: Bereite deine Tabelle für dynamische Inhalte vor

Füge als Nächstes eine id zu deinem Tabellenkörper hinzu, damit JavaScript ihn leicht ansprechen kann:

<tbody id="transactions"></tbody>

Was das bewirkt:

  • Schafft ein klares Ziel für das Einfügen von Transaktionszeilen
  • Trennt die Tabellenstruktur von dynamischen Inhalten
  • Ermöglicht einfaches Leeren und Wiederbefüllen der Transaktionsdaten

Schritt 3: Erstelle die Transaktionszeilen-Fabrikfunktion

Erstelle jetzt eine Funktion, die Transaktionsdaten in HTML-Elemente umwandelt:

function createTransactionRow(transaction) {
  const template = document.getElementById('transaction');
  const transactionRow = template.content.cloneNode(true);
  const tr = transactionRow.querySelector('tr');
  tr.children[0].textContent = transaction.date;
  tr.children[1].textContent = transaction.object;
  tr.children[2].textContent = transaction.amount.toFixed(2);
  return transactionRow;
}

Aufgeschlüsselt macht diese Fabrikfunktion:

  • Findet das Template-Element anhand seiner ID
  • Klont den Template-Inhalt für sichere Manipulation
  • Wählt die Tabellenzeile innerhalb des Klons aus
  • Befüllt jede Zelle mit Transaktionsdaten
  • Formatiert den Betrag mit korrekten Dezimalstellen
  • Gibt die fertige Zeile zur Einfügung zurück

Schritt 4: Effizient mehrere Transaktionszeilen generieren

Füge diesen Code zu deiner updateDashboard()-Funktion hinzu, um alle Transaktionen anzuzeigen:

const transactionsRows = document.createDocumentFragment();
for (const transaction of account.transactions) {
  const transactionRow = createTransactionRow(transaction);
  transactionsRows.appendChild(transactionRow);
}
updateElement('transactions', transactionsRows);

Warum dieser effiziente Ansatz sinnvoll ist:

  • Erstellt ein Dokumentfragment, um DOM-Operationen zu bündeln
  • Iteriert durch alle Transaktionen im Kontodatensatz
  • Generiert für jede Transaktion eine Zeile mittels der Fabrikfunktion
  • Sammelt alle Zeilen im Fragment, bevor sie dem DOM hinzugefügt werden
  • Führt eine einzelne DOM-Aktualisierung statt vieler Einzel-Insertions durch

Leistungsoptimierung: document.createDocumentFragment() funktioniert wie der Montageprozess bei Boeing Komponenten werden außerhalb der Hauptlinie vorbereitet und dann als komplette Einheit eingebaut. Dieser Batch-Ansatz minimiert DOM-Neuberechnungen, indem eine einzige Einfügung statt mehrerer einzelner Operationen durchgeführt wird.

Schritt 5: Verbesserung der Update-Funktion für gemischte Inhalte

Ihre updateElement()-Funktion verarbeitet derzeit nur Textinhalte. Aktualisieren Sie sie so, dass sie sowohl mit Text als auch mit DOM-Knoten funktioniert:

function updateElement(id, textOrNode) {
  const element = document.getElementById(id);
  element.textContent = ''; // Removes all children
  element.append(textOrNode);
}

Wichtige Verbesserungen in diesem Update:

  • Löscht vorhandenen Inhalt, bevor neuer Inhalt hinzugefügt wird
  • Akzeptiert entweder Textstrings oder DOM-Knoten als Parameter
  • Verwendet die append()-Methode für mehr Flexibilität
  • Erhält die Abwärtskompatibilität mit der bisherigen, textbasierten Nutzung

Machen Sie eine Probefahrt mit Ihrem Dashboard

Der Moment der Wahrheit ist gekommen! Sehen wir uns Ihr dynamisches Dashboard in Aktion an:

  1. Melden Sie sich mit dem test-Konto an (es enthält Beispieldaten)
  2. Navigieren Sie zu Ihrem Dashboard
  3. Überprüfen Sie, ob die Transaktionszeilen mit korrekter Formatierung angezeigt werden
  4. Stellen Sie sicher, dass Daten, Beschreibungen und Beträge korrekt dargestellt sind

Wenn alles funktioniert, sollten Sie eine voll funktionsfähige Transaktionsliste auf Ihrem Dashboard sehen! 🎉

Was Sie erreicht haben:

  • Ein Dashboard gebaut, das mit jeder Datenmenge skaliert
  • Wiederverwendbare Templates für eine konsistente Formatierung erstellt
  • Effiziente DOM-Manipulationsmethoden implementiert
  • Funktionen entwickelt, die mit Produktions-Banking-Apps vergleichbar sind

Sie haben erfolgreich eine statische Webseite in eine dynamische Webanwendung verwandelt.

🎯 Pädagogischer Check-in: Dynamische Inhaltserzeugung

Architekturverständnis: Sie haben eine ausgefeilte Daten-zu-UI-Pipeline implementiert, die Muster aus Frameworks wie React, Vue und Angular nachahmt.

Meisterung der Kernkonzepte:

  • Template-basierte Darstellung: Erstellen wiederverwendbarer UI-Komponenten
  • Document Fragments: Optimierung der DOM-Performance
  • Sichere DOM-Manipulation: Vermeidung von Sicherheitslücken
  • Datenumwandlung: Umwandlung von Serverdaten in Benutzeroberflächen

Branchenbezug: Diese Techniken bilden die Grundlage moderner Frontend-Frameworks. Reacts Virtual DOM, Vues Templatesystem und Angulars Komponentenarchitektur basieren alle auf diesen Kernkonzepten.

Reflexionsfrage: Wie würden Sie dieses System erweitern, um Echtzeit-Updates zu verarbeiten (z. B. neue Transaktionen, die automatisch erscheinen)? Denken Sie an WebSockets oder Server-Sent Events.


📈 Ihr Zeitstrahl zur Datenmanagement-Meisterschaft

timeline
    title Datengetriebene Entwicklungsreise
    
    section Fundamentaufbau
        API Einrichtung & Testen
            : Verstehen der Client-Server-Kommunikation
            : Beherrschen des HTTP-Anfrage-/Antwortzyklus
            : Erlernen von Debugging-Techniken
    
    section Authentifizierungsbeherrschung
        Async-Funktionsmuster
            : Sauberen async/await-Code schreiben
            : Versprechen effektiv handhaben
            : Fehlergrenzen implementieren
        Benutzer-Sitzungsverwaltung
            : Globale Zustandsmuster erstellen
            : Navigationsschutz entwickeln
            : Benutzer-Feedback-Systeme gestalten
    
    section Dynamische UI-Entwicklung
        Sichere DOM-Manipulation
            : XSS-Sicherheitslücken verhindern
            : textContent statt innerHTML verwenden
            : Barrierefreie Schnittstellen erstellen
        Templatesysteme
            : Wiederverwendbare UI-Komponenten bauen
            : Leistung mit Fragmenten optimieren
            : Skalieren zur Handhabung großer Datenmengen
    
    section Professionelle Muster
        Produktionsreifer Code
            : Umfassendes Fehlerhandling implementieren
            : Sicherheitsbest Practices befolgen
            : Wartbare Architekturen erstellen
        Moderne Webstandards
            : Fetch API-Muster beherrschen
            : CORS-Konfigurationen verstehen
            : Responsive, zugängliche UIs bauen

🎓 Meilenstein zur Abschlussreife: Sie haben erfolgreich eine vollständige datengetriebene Webanwendung mit modernen JavaScript-Mustern gebaut. Diese Fähigkeiten lassen sich direkt auf Frameworks wie React, Vue oder Angular übertragen.

🔄 Nächste Fähigkeitsstufe:

  • Bereit, Frontend-Frameworks zu erkunden, die auf diesen Konzepten aufbauen
  • Vorbereitet, Echtzeitfunktionen mit WebSockets zu implementieren
  • Ausgestattet, Progressive Web Apps mit Offline-Funktionalität zu erstellen
  • Fundament gelegt für das Lernen fortgeschrittener State-Management-Muster

GitHub Copilot Agent Challenge 🚀

Verwenden Sie den Agent-Modus, um die folgende Herausforderung zu meistern:

Beschreibung: Erweitern Sie die Banking-App durch Implementierung einer Such- und Filterfunktion für Transaktionen, mit der Benutzer bestimmte Transaktionen nach Datumsbereich, Betrag oder Beschreibung finden können.

Eingabeaufforderung: Erstellen Sie eine Suchfunktion für die Banking-App, die umfasst: 1) Ein Suchformular mit Eingabefeldern für Datumsbereich (von/bis), Mindest-/Höchstbetrag und Schlüsselwörter der Transaktionsbeschreibung, 2) Eine filterTransactions()-Funktion, die das account.transactions-Array basierend auf den Suchkriterien filtert, 3) Aktualisieren Sie die updateDashboard()-Funktion, um gefilterte Ergebnisse anzuzeigen, und 4) Fügen Sie eine Schaltfläche „Filter zurücksetzen“ hinzu, um die Ansicht zu reinigen. Verwenden Sie moderne JavaScript-Array-Methoden wie filter() und behandeln Sie Randfälle bei leeren Suchkriterien.

Erfahren Sie mehr über den Agent-Modus.

🚀 Herausforderung

Bereit, Ihre Banking-App auf die nächste Stufe zu heben? Machen wir sie so schön und benutzerfreundlich, dass man sie wirklich gerne nutzen möchte. Hier ein paar Ideen zur Inspiration:

Machen Sie sie schön: Fügen Sie CSS-Styling hinzu, um Ihr funktionales Dashboard visuell ansprechend zu gestalten. Denken Sie an klare Linien, gutes Layout und vielleicht sogar subtile Animationen.

Machen Sie es responsiv: Versuchen Sie, Media Queries zu verwenden, um ein responsives Design zu erstellen, das auf Telefonen, Tablets und Desktops gut funktioniert. Ihre Nutzer werden es Ihnen danken!

Fügen Sie etwas Flair hinzu: Erwägen Sie die Farbkennzeichnung von Transaktionen (grün für Einnahmen, rot für Ausgaben), das Hinzufügen von Symbolen oder Hover-Effekten, die die Benutzeroberfläche interaktiv wirken lassen.

So könnte ein ausgefeiltes Dashboard aussehen:

Screenshot eines Beispielergebnisses des Dashboards nach Styling

Fühlen Sie sich nicht gezwungen, es exakt nachzumachen nutzen Sie es als Inspiration und machen Sie es zu Ihrem eigenen!

Quiz nach der Vorlesung

Quiz nach der Vorlesung

Aufgabe

Refactoren und Kommentieren Ihres Codes


Haftungsausschluss:
Dieses Dokument wurde mithilfe des KI-Übersetzungsdienstes Co-op Translator übersetzt. Obwohl wir uns um Genauigkeit bemühen, kann es bei automatischen Übersetzungen zu Fehlern oder Ungenauigkeiten kommen. Das Originaldokument in der Originalsprache sollte als maßgebliche Quelle betrachtet werden. Für entscheidende Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die durch die Nutzung dieser Übersetzung entstehen.