Skip to content

Kapitel 17: ES6 Praxis-Projekte

17.1 Listenfilterung + Rendering (Array-Methoden + Template Strings)

🎯 Projekt: Produktliste filtern und anzeigen

Szenario: Du hast ein Array von Produkten. Du möchtest:

  1. Produkte nach Preis filtern
  2. Eine HTML-Liste erstellen
  3. Die Liste in einen Container einfügen

📝 Schritt 1: Daten vorbereiten

javascript
const products = [
  { id: 1, name: "Laptop", preis: 999, kategorie: "Elektronik" },
  { id: 2, name: "Maus", preis: 25, kategorie: "Zubehör" },
  { id: 3, name: "Tastatur", preis: 75, kategorie: "Zubehör" },
  { id: 4, name: "Monitor", preis: 300, kategorie: "Elektronik" }
];

📝 Schritt 2: Produkte filtern (teurer als 50 €)

javascript
// ✅ ES6 - filter() + Arrow Function
const expensiveProducts = products.filter(product => product.preis > 50);

console.log(expensiveProducts);
// [
//   { id: 1, name: "Laptop", preis: 999, kategorie: "Elektronik" },
//   { id: 4, name: "Monitor", preis: 300, kategorie: "Elektronik" }
// ]

📝 Schritt 3: HTML-Liste erstellen (Template Strings)

javascript
// ✅ ES6 - map() + Template Strings
const html = `
  <ul class="produkt-liste">
    ${expensiveProducts.map(product => `
      <li class="produkt" data-id="${product.id}">
        <span class="name">${product.name}</span>
        <span class="preis">${product.preis} €</span>
        <span class="kategorie">${product.kategorie}</span>
      </li>
    `).join("")}
  </ul>
`;

console.log(html);

Ausgabe (formatiert):

html
<ul class="produkt-liste">
  <li class="produkt" data-id="1">
    <span class="name">Laptop</span>
    <span class="preis">999 €</span>
    <span class="kategorie">Elektronik</span>
  </li>
  <li class="produkt" data-id="4">
    <span class="name">Monitor</span>
    <span class="preis">300 €</span>
    <span class="kategorie">Elektronik</span>
  </li>
</ul>

📝 Schritt 4: In DOM einfügen

javascript
// ✅ Einfügen in DOM
document.getElementById("app").innerHTML = html;

🎉 Zusammenfassung

Verwendete ES6-Konzepte:

  • Arrow Functions (product => product.preis > 50)
  • Array-Methoden (filter(), map())
  • Template Strings (`${product.name}`)
  • Method Chaining (Verkettung von filter() und map())

17.2 Asynchrone Datenanzeige (Promise + async/await)

🎯 Projekt: Benutzerdaten asynchron laden

Szenario: Du möchtest Benutzerdaten von einer API laden und anzeigen.


📝 Schritt 1: Promise-Simulation (API-Aufruf)

javascript
// ✅ Promise erstellen (simuliert API-Aufruf)
function fetchUser() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = true;
      if (success) {
        resolve({
          id: 1,
          name: "Max Mustermann",
          email: "max@example.com"
        });
      } else {
        reject("Fehler beim Laden der Benutzerdaten");
      }
    }, 1000);
  });
}

📝 Schritt 2: Daten mit Promise.then() anzeigen

javascript
// ✅ Mit Promise.then()
fetchUser()
  .then(user => {
    const html = `
      <div class="user-card">
        <h2>${user.name}</h2>
        <p>Email: ${user.email}</p>
      </div>
    `;
    document.getElementById("app").innerHTML = html;
  })
  .catch(error => {
    console.error(error);
    document.getElementById("app").innerHTML = `<p class="error">${error}</p>`;
  })
  .finally(() => {
    console.log("Datenabfrage beendet");
  });

📝 Schritt 3: Daten mit async/await anzeigen (moderner!)

javascript
// ✅ Mit async/await (eleganter!)
async function displayUser() {
  try {
    const user = await fetchUser();
    
    const html = `
      <div class="user-card">
        <h2>${user.name}</h2>
        <p>Email: ${user.email}</p>
      </div>
    `;
    document.getElementById("app").innerHTML = html;
  } catch (error) {
    console.error(error);
    document.getElementById("app").innerHTML = `<p class="error">${error}</p>`;
  } finally {
    console.log("Datenabfrage beendet");
  }
}

// Aufrufen
displayUser();

🎉 Zusammenfassung

Verwendete ES6-Konzepte:

  • Promise (new Promise(), resolve, reject)
  • Promise-Methoden (.then(), .catch(), .finally())
  • async/await (async function, await)
  • Template Strings (`${user.name}`)
  • Fehlerbehandlung (try...catch)

17.3 Code in Module aufteilen (import/export)

🎯 Projekt: Modulare Code-Struktur

Szenario: Du möchtest deinen Code in mehrere Dateien aufteilen (Modularisierung).


📂 Projektstruktur

src/
├── main.js          ← Einstiegspunkt
├── models/
│   └── User.js     ← User-Klasse
└── utils/
    ├── dom.js      ← DOM-Hilfsfunktionen
    └── api.js      ← API-Aufrufe

📝 Schritt 1: User.js (Default Export)

javascript
// src/models/User.js

// Klasse definieren
class User {
  constructor(id, name, email) {
    this.id = id;
    this.name = name;
    this.email = email;
  }

  getInfo() {
    return `${this.name} (${this.email})`;
  }
}

// ✅ Default Export
export default User;

📝 Schritt 2: dom.js (Named Exports)

javascript
// src/utils/dom.js

// ✅ Named Exports
export function getElement(id) {
  return document.getElementById(id);
}

export function setHTML(element, html) {
  if (typeof element === "string") {
    element = getElement(element);
  }
  element.innerHTML = html;
}

export function createElement(tag, attributes = {}) {
  const element = document.createElement(tag);
  Object.entries(attributes).forEach(([key, value]) => {
    element.setAttribute(key, value);
  });
  return element;
}

📝 Schritt 3: api.js (Named + Default Exports)

javascript
// src/utils/api.js

// Hilfsfunktion (privat)
function simulateDelay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// ✅ Named Export
export async function fetchUser(id) {
  await simulateDelay(1000);
  return {
    id,
    name: "Max Mustermann",
    email: "max@example.com"
  };
}

export async function fetchUsers() {
  await simulateDelay(1000);
  return [
    { id: 1, name: "Max", email: "max@example.com" },
    { id: 2, name: "Erika", email: "erika@example.com" }
  ];
}

// ✅ Default Export (Haupt-Export)
const API = {
  fetchUser,
  fetchUsers
};

export default API;

📝 Schritt 4: main.js (Importe)

javascript
// src/main.js

// ✅ Default Import
import User from './models/User.js';

// ✅ Named Imports
import { getElement, setHTML, createElement } from './utils/dom.js';

// ✅ Kombination (Default + Named)
import API, { fetchUser, fetchUsers } from './utils/api.js';

// ====== Verwendung ======

async function init() {
  try {
    // 1. Benutzer laden
    const userData = await fetchUser(1);
    
    // 2. User-Instanz erstellen
    const user = new User(userData.id, userData.name, userData.email);
    
    // 3. HTML erstellen
    const html = `
      <div class="user-card">
        <h2>${user.name}</h2>
        <p>Email: ${user.email}</p>
        <p>Info: ${user.getInfo()}</p>
      </div>
    `;
    
    // 4. In DOM einfügen
    setHTML("app", html);
  } catch (error) {
    console.error("Fehler:", error);
  }
}

// Anwendung starten
init();

🎉 Zusammenfassung

Verwendete ES6-Konzepte:

  • Export/Import (export, import)
  • Default Export (export default ...)
  • Named Export (export function ...)
  • Klassen (class User {})
  • async/await (async function, await)
  • Template Strings (`${user.name}`)
  • Destructuring ({ getElement, setHTML })

17.4 OOP-Kleinebeispiele (Class)

🎯 Projekt: Einfaches ToDo-System (OOP)

Szenario: Du möchtest ein einfaches ToDo-System mit OOP (Object-Oriented Programming) erstellen.


📝 Schritt 1: Todo-Klasse

javascript
// src/models/Todo.js

class Todo {
  constructor(id, title, completed = false) {
    this.id = id;
    this.title = title;
    this.completed = completed;
    this.createdAt = new Date();
  }

  // Methode: ToDo als abgeschlossen markieren
  complete() {
    this.completed = true;
    console.log(`ToDo "${this.title}" abgeschlossen! ✅`);
  }

  // Methode: ToDo als offen markieren
  reopen() {
    this.completed = false;
    console.log(`ToDo "${this.title}" wieder geöffnet! 🔄`);
  }

  // Methode: Informationen abrufen
  getInfo() {
    return `${this.title} (${this.completed ? "Abgeschlossen" : "Offen"})`;
  }
}

// ✅ Export
export default Todo;

📝 Schritt 2: TodoList-Klasse (Vererbung nicht nötig, Komposition!)

javascript
// src/models/TodoList.js
import Todo from './Todo.js';

class TodoList {
  constructor(name) {
    this.name = name;
    this.todos = [];
    this.nextId = 1;
  }

  // Methode: ToDo hinzufügen
  add(title) {
    const todo = new Todo(this.nextId++, title);
    this.todos.push(todo);
    console.log(`ToDo hinzugefügt: ${title}`);
    return todo;
  }

  // Methode: ToDo entfernen
  remove(id) {
    this.todos = this.todos.filter(todo => todo.id !== id);
    console.log(`ToDo mit ID ${id} entfernt`);
  }

  // Methode: Alle offenen ToDos anzeigen
  getOpenTodos() {
    return this.todos.filter(todo => !todo.completed);
  }

  // Methode: Alle abgeschlossenen ToDos anzeigen
  getCompletedTodos() {
    return this.todos.filter(todo => todo.completed);
  }

  // Methode: Statistik abrufen
  getStats() {
    const total = this.todos.length;
    const completed = this.getCompletedTodos().length;
    const open = total - completed;
    return { total, completed, open };
  }
}

// ✅ Export
export default TodoList;

📝 Schritt 3: Anwendung (main.js)

javascript
// src/main.js
import TodoList from './models/TodoList.js';

// 1. ToDo-Liste erstellen
const myList = new TodoList("Meine Aufgaben");

// 2. ToDos hinzufügen
myList.add("ES6 lernen");
myList.add("Projekt beenden");
myList.add("Kaffee trinken ☕");

// 3. Ein ToDo als abgeschlossen markieren
myList.todos[0].complete();

// 4. Statistik anzeigen
const stats = myList.getStats();
console.log(`Statistik: ${stats.total} total, ${stats.completed} abgeschlossen, ${stats.open} offen`);
// Ausgabe: "Statistik: 3 total, 1 abgeschlossen, 2 offen"

// 5. Offene ToDos anzeigen
console.log("Offene ToDos:", myList.getOpenTodos().map(t => t.getInfo()));

// 6. Abgeschlossene ToDos anzeigen
console.log("Abgeschlossene ToDos:", myList.getCompletedTodos().map(t => t.getInfo()));

📝 Schritt 4: Erweiterung (Vererbung - Fortgeschritten)

javascript
// src/models/PrioritizedTodo.js
import Todo from './Todo.js';

// ✅ Vererbung (extends)
class PrioritizedTodo extends Todo {
  constructor(id, title, priority = "mittel") {
    super(id, title);
    this.priority = priority; // "hoch", "mittel", "niedrig"
  }

  // Überschreiben der getInfo()-Methode
  getInfo() {
    const baseInfo = super.getInfo();
    return `${baseInfo} [Priorität: ${this.priority}]`;
  }
}

// ✅ Export
export default PrioritizedTodo;

🎉 Zusammenfassung

Verwendete ES6-Konzepte:

  • Klassen (class Todo {})
  • Konstruktor (constructor() {})
  • Methoden (complete() {})
  • Vererbung (extends, super())
  • Import/Export (import, export default)
  • Array-Methoden (filter(), map())

🎉 Kapitel-Zusammenfassung

In diesem Kapitel hast du gelernt:

  • Listenfilterung + Rendering (Array-Methoden, Template Strings)
  • Asynchrone Datenanzeige (Promise, async/await)
  • Code in Module aufteilen (import/export)
  • OOP-Kleinebeispiele (Class, Vererbung)

📝 Übung

  1. Listenfilterung:

    javascript
    const numbers = [1, 2, 3, 4, 5, 6];
    // Filtere nur gerade Zahlen und erstelle eine HTML-Liste
  2. Asynchrone Datenanzeige:

    javascript
    // Simuliere einen API-Aufruf mit Promise, der eine Liste von Benutzern zurückgibt
    // Verwende async/await, um die Daten zu laden und anzuzeigen
  3. Modularisierung:

    javascript
    // Erstelle eine Klasse "Book" in einer separaten Datei
    // Importiere sie in main.js und verwende sie
  4. OOP:

    javascript
    // Erstelle eine Klasse "Animal" und eine abgeleitete Klasse "Dog"
    // "Dog" soll eine Methode "bark()" haben

➡️ Nächstes Kapitel

In Kapitel 18 lernen wir ES6-Häufig gestellte Interviewfragen - perfekt, um dich auf dein nächstes Interview vorzubereiten!

Frei für alle Anfänger