parent
c5cbfd388d
commit
9823536d1d
@ -0,0 +1,215 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "c63675cfaf1d223b37bb9fecbfe7c252",
|
||||
"translation_date": "2025-08-24T12:58:43+00:00",
|
||||
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Einführung in Programmiersprachen und Werkzeuge des Handwerks
|
||||
|
||||
Diese Lektion behandelt die Grundlagen von Programmiersprachen. Die hier behandelten Themen gelten für die meisten modernen Programmiersprachen. Im Abschnitt "Werkzeuge des Handwerks" lernst du nützliche Software kennen, die dir als Entwickler:in hilft.
|
||||
|
||||

|
||||
> Sketchnote von [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
[Quiz vor der Vorlesung](https://forms.office.com/r/dru4TE0U9n?origin=lprLink)
|
||||
|
||||
## Einführung
|
||||
|
||||
In dieser Lektion behandeln wir:
|
||||
|
||||
- Was ist Programmieren?
|
||||
- Arten von Programmiersprachen
|
||||
- Grundelemente eines Programms
|
||||
- Nützliche Software und Werkzeuge für professionelle Entwickler:innen
|
||||
|
||||
> Du kannst diese Lektion auf [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/introduction-programming/?WT.mc_id=academic-77807-sagibbon) absolvieren!
|
||||
|
||||
## Was ist Programmieren?
|
||||
|
||||
Programmieren (auch bekannt als Codieren) ist der Prozess, Anweisungen für ein Gerät wie einen Computer oder ein mobiles Gerät zu schreiben. Wir schreiben diese Anweisungen mit einer Programmiersprache, die dann vom Gerät interpretiert wird. Diese Anweisungen können verschiedene Namen haben, aber *Programm*, *Computerprogramm*, *Anwendung (App)* und *ausführbare Datei* sind einige gängige Bezeichnungen.
|
||||
|
||||
Ein *Programm* kann alles sein, was mit Code geschrieben wurde; Websites, Spiele und Handy-Apps sind Programme. Auch wenn es möglich ist, ein Programm ohne Code zu erstellen, wird die zugrunde liegende Logik vom Gerät interpretiert, und diese Logik wurde höchstwahrscheinlich mit Code geschrieben. Ein Programm, das *läuft* oder *ausgeführt* wird, führt Anweisungen aus. Das Gerät, mit dem du diese Lektion liest, führt ein Programm aus, um sie auf deinem Bildschirm anzuzeigen.
|
||||
|
||||
✅ Recherchiere ein wenig: Wer gilt als der/die erste Computerprogrammierer:in der Welt?
|
||||
|
||||
## Programmiersprachen
|
||||
|
||||
Programmiersprachen ermöglichen es Entwickler:innen, Anweisungen für ein Gerät zu schreiben. Geräte können nur Binärcode (1en und 0en) verstehen, und für *die meisten* Entwickler:innen ist das keine sehr effiziente Art der Kommunikation. Programmiersprachen sind das Mittel zur Kommunikation zwischen Menschen und Computern.
|
||||
|
||||
Programmiersprachen gibt es in verschiedenen Formaten und sie können unterschiedlichen Zwecken dienen. Zum Beispiel wird JavaScript hauptsächlich für Webanwendungen verwendet, während Bash hauptsächlich für Betriebssysteme genutzt wird.
|
||||
|
||||
*Low-Level-Sprachen* erfordern in der Regel weniger Schritte als *High-Level-Sprachen*, damit ein Gerät Anweisungen interpretieren kann. Was High-Level-Sprachen jedoch beliebt macht, ist ihre Lesbarkeit und Unterstützung. JavaScript gilt als High-Level-Sprache.
|
||||
|
||||
Der folgende Code zeigt den Unterschied zwischen einer High-Level-Sprache wie JavaScript und einer Low-Level-Sprache wie ARM-Assemblercode.
|
||||
|
||||
```javascript
|
||||
let number = 10
|
||||
let n1 = 0, n2 = 1, nextTerm;
|
||||
|
||||
for (let i = 1; i <= number; i++) {
|
||||
console.log(n1);
|
||||
nextTerm = n1 + n2;
|
||||
n1 = n2;
|
||||
n2 = nextTerm;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
area ascen,code,readonly
|
||||
entry
|
||||
code32
|
||||
adr r0,thumb+1
|
||||
bx r0
|
||||
code16
|
||||
thumb
|
||||
mov r0,#00
|
||||
sub r0,r0,#01
|
||||
mov r1,#01
|
||||
mov r4,#10
|
||||
ldr r2,=0x40000000
|
||||
back add r0,r1
|
||||
str r0,[r2]
|
||||
add r2,#04
|
||||
mov r3,r0
|
||||
mov r0,r1
|
||||
mov r1,r3
|
||||
sub r4,#01
|
||||
cmp r4,#00
|
||||
bne back
|
||||
end
|
||||
```
|
||||
|
||||
Glaub es oder nicht, *sie tun beide dasselbe*: Sie geben eine Fibonacci-Sequenz bis 10 aus.
|
||||
|
||||
✅ Eine Fibonacci-Sequenz wird [definiert](https://en.wikipedia.org/wiki/Fibonacci_number) als eine Reihe von Zahlen, bei der jede Zahl die Summe der beiden vorhergehenden ist, beginnend mit 0 und 1. Die ersten 10 Zahlen der Fibonacci-Sequenz sind 0, 1, 1, 2, 3, 5, 8, 13, 21 und 34.
|
||||
|
||||
## Elemente eines Programms
|
||||
|
||||
Eine einzelne Anweisung in einem Programm wird als *Statement* bezeichnet und hat normalerweise ein Zeichen oder einen Zeilenabstand, der markiert, wo die Anweisung endet oder *terminiert*. Wie ein Programm terminiert, variiert je nach Sprache.
|
||||
|
||||
Anweisungen in einem Programm können von Daten abhängen, die von einem Benutzer oder einer anderen Quelle bereitgestellt werden, um Anweisungen auszuführen. Daten können beeinflussen, wie sich ein Programm verhält, daher bieten Programmiersprachen eine Möglichkeit, Daten vorübergehend zu speichern, damit sie später verwendet werden können. Diese werden als *Variablen* bezeichnet. Variablen sind Anweisungen, die ein Gerät anweisen, Daten im Speicher zu speichern. Variablen in Programmen ähneln Variablen in der Algebra, da sie einen eindeutigen Namen haben und sich ihr Wert im Laufe der Zeit ändern kann.
|
||||
|
||||
Es besteht die Möglichkeit, dass einige Anweisungen von einem Gerät nicht ausgeführt werden. Dies geschieht in der Regel absichtlich, wenn es vom Entwickler so geschrieben wurde, oder versehentlich, wenn ein unerwarteter Fehler auftritt. Diese Art der Kontrolle über eine Anwendung macht sie robuster und wartbarer. Typischerweise treten diese Kontrolländerungen auf, wenn bestimmte Bedingungen erfüllt sind. Eine gängige Anweisung in modernen Programmiersprachen, um zu steuern, wie ein Programm ausgeführt wird, ist die `if..else`-Anweisung.
|
||||
|
||||
✅ Du wirst mehr über diese Art von Anweisungen in späteren Lektionen lernen.
|
||||
|
||||
## Werkzeuge des Handwerks
|
||||
|
||||
[](https://youtube.com/watch?v=69WJeXGBdxg "Werkzeuge des Handwerks")
|
||||
|
||||
> 🎥 Klicke auf das Bild oben, um ein Video über Werkzeuge anzusehen
|
||||
|
||||
In diesem Abschnitt lernst du einige Software kennen, die du als nützlich empfinden könntest, wenn du deine Reise als professionelle:r Entwickler:in beginnst.
|
||||
|
||||
Eine **Entwicklungsumgebung** ist eine einzigartige Sammlung von Werkzeugen und Funktionen, die ein:e Entwickler:in häufig beim Schreiben von Software verwendet. Einige dieser Werkzeuge wurden speziell auf die Bedürfnisse eines:einer Entwickler:in zugeschnitten und können sich im Laufe der Zeit ändern, wenn sich die Prioritäten in der Arbeit, bei persönlichen Projekten oder bei der Verwendung einer anderen Programmiersprache ändern. Entwicklungsumgebungen sind so einzigartig wie die Entwickler:innen, die sie nutzen.
|
||||
|
||||
### Editoren
|
||||
|
||||
Eines der wichtigsten Werkzeuge für die Softwareentwicklung ist der Editor. Editoren sind der Ort, an dem du deinen Code schreibst und manchmal auch ausführst.
|
||||
|
||||
Entwickler:innen verlassen sich aus mehreren Gründen auf Editoren:
|
||||
|
||||
- *Debugging* hilft, Fehler und Probleme aufzudecken, indem der Code Zeile für Zeile durchgegangen wird. Einige Editoren verfügen über Debugging-Funktionen, die für bestimmte Programmiersprachen angepasst und hinzugefügt werden können.
|
||||
- *Syntaxhervorhebung* fügt Farben und Textformatierungen zum Code hinzu, was ihn leichter lesbar macht. Die meisten Editoren erlauben eine angepasste Syntaxhervorhebung.
|
||||
- *Erweiterungen und Integrationen* sind spezialisierte Werkzeuge für Entwickler:innen, die von anderen Entwickler:innen erstellt wurden. Diese Werkzeuge sind nicht im Basis-Editor enthalten. Zum Beispiel dokumentieren viele Entwickler:innen ihren Code, um zu erklären, wie er funktioniert. Sie könnten eine Rechtschreibprüfungserweiterung installieren, um Tippfehler in der Dokumentation zu finden. Die meisten Erweiterungen sind für die Verwendung in einem bestimmten Editor gedacht, und die meisten Editoren bieten eine Möglichkeit, nach verfügbaren Erweiterungen zu suchen.
|
||||
- *Anpassung* ermöglicht es Entwickler:innen, eine einzigartige Entwicklungsumgebung zu schaffen, die ihren Bedürfnissen entspricht. Die meisten Editoren sind extrem anpassbar und erlauben es Entwickler:innen, eigene Erweiterungen zu erstellen.
|
||||
|
||||
#### Beliebte Editoren und Webentwicklungs-Erweiterungen
|
||||
|
||||
- [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
|
||||
- [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare)
|
||||
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
- [Atom](https://atom.io/)
|
||||
- [spell-check](https://atom.io/packages/spell-check)
|
||||
- [teletype](https://atom.io/packages/teletype)
|
||||
- [atom-beautify](https://atom.io/packages/atom-beautify)
|
||||
|
||||
- [Sublimetext](https://www.sublimetext.com/)
|
||||
- [emmet](https://emmet.io/)
|
||||
- [SublimeLinter](http://www.sublimelinter.com/en/stable/)
|
||||
|
||||
### Browser
|
||||
|
||||
Ein weiteres wichtiges Werkzeug ist der Browser. Webentwickler:innen verlassen sich auf den Browser, um zu sehen, wie ihr Code im Web ausgeführt wird. Er wird auch verwendet, um die visuellen Elemente einer Webseite anzuzeigen, die im Editor geschrieben wurden, wie HTML.
|
||||
|
||||
Viele Browser verfügen über *Entwicklerwerkzeuge* (DevTools), die eine Reihe hilfreicher Funktionen und Informationen enthalten, um Entwickler:innen dabei zu helfen, wichtige Informationen über ihre Anwendung zu sammeln und zu erfassen. Zum Beispiel: Wenn eine Webseite Fehler hat, ist es manchmal hilfreich zu wissen, wann sie aufgetreten sind. DevTools in einem Browser können so konfiguriert werden, dass diese Informationen erfasst werden.
|
||||
|
||||
#### Beliebte Browser und DevTools
|
||||
|
||||
- [Edge](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [Chrome](https://developers.google.com/web/tools/chrome-devtools/)
|
||||
- [Firefox](https://developer.mozilla.org/docs/Tools)
|
||||
|
||||
### Kommandozeilenwerkzeuge
|
||||
|
||||
Einige Entwickler:innen bevorzugen eine weniger grafische Ansicht für ihre täglichen Aufgaben und verlassen sich auf die Kommandozeile, um dies zu erreichen. Das Schreiben von Code erfordert eine erhebliche Menge an Tippen, und einige Entwickler:innen bevorzugen es, ihren Arbeitsfluss auf der Tastatur nicht zu unterbrechen. Sie verwenden Tastenkombinationen, um zwischen Desktop-Fenstern zu wechseln, an verschiedenen Dateien zu arbeiten und Werkzeuge zu nutzen. Die meisten Aufgaben können mit einer Maus erledigt werden, aber ein Vorteil der Kommandozeile ist, dass vieles mit Kommandozeilenwerkzeugen erledigt werden kann, ohne zwischen Maus und Tastatur wechseln zu müssen. Ein weiterer Vorteil der Kommandozeile ist, dass sie konfigurierbar ist und du eine benutzerdefinierte Konfiguration speichern, später ändern und auf andere Entwicklungsmaschinen importieren kannst. Da Entwicklungsumgebungen so einzigartig für jede:n Entwickler:in sind, vermeiden einige die Kommandozeile, andere verlassen sich vollständig darauf, und wieder andere bevorzugen eine Mischung aus beidem.
|
||||
|
||||
### Beliebte Kommandozeilenoptionen
|
||||
|
||||
Die Optionen für die Kommandozeile unterscheiden sich je nach Betriebssystem.
|
||||
|
||||
*💻 = ist standardmäßig auf dem Betriebssystem vorinstalliert.*
|
||||
|
||||
#### Windows
|
||||
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/overview?view=powershell-7/?WT.mc_id=academic-77807-sagibbon) 💻
|
||||
- [Command Line](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands/?WT.mc_id=academic-77807-sagibbon) (auch bekannt als CMD) 💻
|
||||
- [Windows Terminal](https://docs.microsoft.com/windows/terminal/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [mintty](https://mintty.github.io/)
|
||||
|
||||
#### MacOS
|
||||
|
||||
- [Terminal](https://support.apple.com/guide/terminal/open-or-quit-terminal-apd5265185d-f365-44cb-8b09-71a064a42125/mac) 💻
|
||||
- [iTerm](https://iterm2.com/)
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
|
||||
|
||||
#### Linux
|
||||
|
||||
- [Bash](https://www.gnu.org/software/bash/manual/html_node/index.html) 💻
|
||||
- [KDE Konsole](https://docs.kde.org/trunk5/en/konsole/konsole/index.html)
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
|
||||
|
||||
#### Beliebte Kommandozeilenwerkzeuge
|
||||
|
||||
- [Git](https://git-scm.com/) (💻 auf den meisten Betriebssystemen)
|
||||
- [NPM](https://www.npmjs.com/)
|
||||
- [Yarn](https://classic.yarnpkg.com/en/docs/cli/)
|
||||
|
||||
### Dokumentation
|
||||
|
||||
Wenn ein:e Entwickler:in etwas Neues lernen möchte, wird er:sie sich höchstwahrscheinlich an die Dokumentation wenden, um zu erfahren, wie man es benutzt. Entwickler:innen verlassen sich oft auf Dokumentationen, um sich darüber zu informieren, wie Werkzeuge und Sprachen richtig verwendet werden, und um ein tieferes Verständnis dafür zu erlangen, wie sie funktionieren.
|
||||
|
||||
#### Beliebte Dokumentationen zur Webentwicklung
|
||||
|
||||
- [Mozilla Developer Network (MDN)](https://developer.mozilla.org/docs/Web), von Mozilla, den Herausgebern des [Firefox](https://www.mozilla.org/firefox/)-Browsers
|
||||
- [Frontend Masters](https://frontendmasters.com/learn/)
|
||||
- [Web.dev](https://web.dev), von Google, den Herausgebern von [Chrome](https://www.google.com/chrome/)
|
||||
- [Microsofts eigene Entwicklerdokumentation](https://docs.microsoft.com/microsoft-edge/#microsoft-edge-for-developers), für [Microsoft Edge](https://www.microsoft.com/edge)
|
||||
- [W3 Schools](https://www.w3schools.com/where_to_start.asp)
|
||||
|
||||
✅ Recherchiere: Jetzt, da du die Grundlagen der Umgebung eines Webentwicklers kennst, vergleiche sie mit der Umgebung eines Webdesigners.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Vergleiche einige Programmiersprachen. Was sind einige der einzigartigen Merkmale von JavaScript im Vergleich zu Java? Wie sieht es mit COBOL im Vergleich zu Go aus?
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/2)
|
||||
|
||||
## Wiederholung & Selbststudium
|
||||
|
||||
Lerne ein wenig über die verschiedenen Programmiersprachen, die einem Programmierer zur Verfügung stehen. Versuche, eine Zeile in einer Sprache zu schreiben, und schreibe sie dann in zwei anderen Sprachen um. Was hast du dabei gelernt?
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Die Dokumentation lesen](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "1ce4deaec80130d3a0a3c906568459fc",
|
||||
"translation_date": "2025-08-24T13:01:28+00:00",
|
||||
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Lesen der Dokumentation
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Es gibt viele Werkzeuge, die ein Webentwickler benötigen könnte, die in der [MDN-Dokumentation für clientseitige Tools](https://developer.mozilla.org/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview) aufgeführt sind. Wähle 3 Werkzeuge aus, die im Unterricht nicht behandelt wurden, erkläre, warum ein Webentwickler sie verwenden würde, und suche ein Werkzeug, das in diese Kategorie fällt, und teile dessen Dokumentation. Verwende nicht dasselbe Werkzeugbeispiel aus den MDN-Dokumenten.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
Vorbildlich | Angemessen | Verbesserungswürdig
|
||||
--- | --- | -- |
|
||||
| Erklärt, warum ein Webentwickler das Werkzeug verwenden würde | Erklärt, wie, aber nicht warum ein Entwickler das Werkzeug verwenden würde | Hat nicht erwähnt, wie oder warum ein Entwickler das Werkzeug verwenden würde |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,241 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "e4cd5b1faed4adab5acf720f82798003",
|
||||
"translation_date": "2025-08-24T12:53:27+00:00",
|
||||
"source_file": "1-getting-started-lessons/3-accessibility/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstellen barrierefreier Webseiten
|
||||
|
||||

|
||||
> Sketchnote von [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/5)
|
||||
|
||||
> Die Stärke des Webs liegt in seiner Universalität. Der Zugang für alle, unabhängig von Behinderung, ist ein wesentlicher Aspekt.
|
||||
>
|
||||
> \- Sir Timothy Berners-Lee, W3C-Direktor und Erfinder des World Wide Web
|
||||
|
||||
Dieses Zitat unterstreicht perfekt die Bedeutung der Erstellung barrierefreier Websites. Eine Anwendung, die nicht von allen genutzt werden kann, ist per Definition ausschließend. Als Webentwickler sollten wir Barrierefreiheit immer im Blick haben. Wenn Sie diesen Fokus von Anfang an haben, sind Sie auf dem besten Weg, sicherzustellen, dass jeder Zugang zu den von Ihnen erstellten Seiten hat. In dieser Lektion lernen Sie die Werkzeuge kennen, die Ihnen helfen, sicherzustellen, dass Ihre Webinhalte barrierefrei sind, und wie Sie mit Barrierefreiheit im Hinterkopf entwickeln können.
|
||||
|
||||
> Sie können diese Lektion auf [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/accessibility/?WT.mc_id=academic-77807-sagibbon) absolvieren!
|
||||
|
||||
## Zu verwendende Werkzeuge
|
||||
|
||||
### Screenreader
|
||||
|
||||
Eines der bekanntesten Barrierefreiheitswerkzeuge sind Screenreader.
|
||||
|
||||
[Screenreader](https://en.wikipedia.org/wiki/Screen_reader) sind häufig genutzte Clients für Menschen mit Sehbehinderungen. Während wir Zeit darauf verwenden, sicherzustellen, dass ein Browser die Informationen, die wir teilen möchten, korrekt darstellt, müssen wir auch sicherstellen, dass ein Screenreader dies tut.
|
||||
|
||||
Ein Screenreader liest eine Seite von oben nach unten hörbar vor. Wenn Ihre Seite nur aus Text besteht, wird der Reader die Informationen ähnlich wie ein Browser vermitteln. Natürlich sind Webseiten selten rein textbasiert; sie enthalten Links, Grafiken, Farben und andere visuelle Komponenten. Es muss darauf geachtet werden, dass diese Informationen korrekt von einem Screenreader gelesen werden.
|
||||
|
||||
Jeder Webentwickler sollte sich mit einem Screenreader vertraut machen. Wie oben hervorgehoben, ist es der Client, den Ihre Nutzer verwenden werden. Genauso wie Sie wissen, wie ein Browser funktioniert, sollten Sie lernen, wie ein Screenreader funktioniert. Glücklicherweise sind Screenreader in den meisten Betriebssystemen integriert.
|
||||
|
||||
Einige Browser haben auch integrierte Tools und Erweiterungen, die Text laut vorlesen oder sogar grundlegende Navigationsfunktionen bieten, wie [diese barrierefreiheitsorientierten Edge-Browser-Tools](https://support.microsoft.com/help/4000734/microsoft-edge-accessibility-features). Diese sind ebenfalls wichtige Barrierefreiheitswerkzeuge, funktionieren jedoch ganz anders als Screenreader und sollten nicht mit Screenreader-Testtools verwechselt werden.
|
||||
|
||||
✅ Probieren Sie einen Screenreader und einen Browser-Textleser aus. Unter Windows ist [Narrator](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon) standardmäßig enthalten, und [JAWS](https://webaim.org/articles/jaws/) und [NVDA](https://www.nvaccess.org/about-nvda/) können ebenfalls installiert werden. Unter macOS und iOS ist [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10) standardmäßig installiert.
|
||||
|
||||
### Zoom
|
||||
|
||||
Ein weiteres Werkzeug, das häufig von Menschen mit Sehbehinderungen verwendet wird, ist das Zoomen. Die einfachste Art des Zoomens ist statisches Zoomen, gesteuert durch `Control + Pluszeichen (+)` oder durch das Verringern der Bildschirmauflösung. Diese Art des Zoomens bewirkt, dass die gesamte Seite vergrößert wird. Daher ist es wichtig, [responsives Design](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Responsive_Design) zu verwenden, um eine gute Benutzererfahrung bei erhöhten Zoomstufen zu gewährleisten.
|
||||
|
||||
Eine andere Art des Zoomens basiert auf spezieller Software, die einen Bereich des Bildschirms vergrößert und schwenkt, ähnlich wie bei der Verwendung einer echten Lupe. Unter Windows ist [Magnifier](https://support.microsoft.com/windows/use-magnifier-to-make-things-on-the-screen-easier-to-see-414948ba-8b1c-d3bd-8615-0e5e32204198) integriert, und [ZoomText](https://www.freedomscientific.com/training/zoomtext/getting-started/) ist eine Drittanbieter-Vergrößerungssoftware mit mehr Funktionen und einer größeren Nutzerbasis. Sowohl macOS als auch iOS verfügen über eine integrierte Vergrößerungssoftware namens [Zoom](https://www.apple.com/accessibility/mac/vision/).
|
||||
|
||||
### Kontrastprüfer
|
||||
|
||||
Farben auf Websites müssen sorgfältig ausgewählt werden, um den Bedürfnissen von farbenblinden Nutzern oder Menschen, die Schwierigkeiten haben, Farben mit geringem Kontrast zu sehen, gerecht zu werden.
|
||||
|
||||
✅ Testen Sie eine Website, die Sie gerne nutzen, auf Farbverwendung mit einer Browser-Erweiterung wie [WCAGs Farbprüfer](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US&WT.mc_id=academic-77807-sagibbon). Was lernen Sie?
|
||||
|
||||
### Lighthouse
|
||||
|
||||
Im Entwicklerbereich Ihres Browsers finden Sie das Lighthouse-Tool. Dieses Tool ist wichtig, um einen ersten Überblick über die Barrierefreiheit (sowie andere Analysen) einer Website zu erhalten. Während es wichtig ist, sich nicht ausschließlich auf Lighthouse zu verlassen, ist eine 100%-Bewertung als Ausgangspunkt sehr hilfreich.
|
||||
|
||||
✅ Finden Sie Lighthouse im Entwicklerbereich Ihres Browsers und führen Sie eine Analyse auf einer beliebigen Website durch. Was entdecken Sie?
|
||||
|
||||
## Gestaltung für Barrierefreiheit
|
||||
|
||||
Barrierefreiheit ist ein relativ großes Thema. Um Ihnen zu helfen, stehen zahlreiche Ressourcen zur Verfügung.
|
||||
|
||||
- [Accessible U - University of Minnesota](https://accessibility.umn.edu/your-role/web-developers)
|
||||
|
||||
Während wir nicht jeden Aspekt der Erstellung barrierefreier Websites abdecken können, finden Sie unten einige der Kernprinzipien, die Sie umsetzen sollten. Eine barrierefreie Seite von Anfang an zu gestalten ist **immer** einfacher, als eine bestehende Seite nachträglich barrierefrei zu machen.
|
||||
|
||||
## Gute Anzeigeprinzipien
|
||||
|
||||
### Farbpaletten, die sicher sind
|
||||
|
||||
Menschen sehen die Welt auf unterschiedliche Weise, und dazu gehören auch Farben. Wenn Sie ein Farbschema für Ihre Website auswählen, sollten Sie sicherstellen, dass es für alle zugänglich ist. Ein großartiges [Tool zur Erstellung von Farbpaletten ist Color Safe](http://colorsafe.co/).
|
||||
|
||||
✅ Identifizieren Sie eine Website, die in ihrer Farbverwendung sehr problematisch ist. Warum?
|
||||
|
||||
### Verwenden Sie das richtige HTML
|
||||
|
||||
Mit CSS und JavaScript ist es möglich, jedes Element wie jede Art von Steuerung aussehen zu lassen. `<span>` könnte verwendet werden, um einen `<button>` zu erstellen, und `<b>` könnte zu einem Hyperlink werden. Obwohl dies möglicherweise einfacher zu gestalten ist, vermittelt es einem Screenreader nichts. Verwenden Sie das passende HTML, wenn Sie Steuerungen auf einer Seite erstellen. Wenn Sie einen Hyperlink möchten, verwenden Sie `<a>`. Die Verwendung des richtigen HTML für die richtige Steuerung wird als Nutzung von semantischem HTML bezeichnet.
|
||||
|
||||
✅ Gehen Sie zu einer beliebigen Website und prüfen Sie, ob die Designer und Entwickler HTML korrekt verwenden. Können Sie einen Button finden, der ein Link sein sollte? Hinweis: Rechtsklicken Sie und wählen Sie 'Seitenquelltext anzeigen' in Ihrem Browser, um den zugrunde liegenden Code zu sehen.
|
||||
|
||||
### Erstellen Sie eine beschreibende Überschriftenhierarchie
|
||||
|
||||
Screenreader-Nutzer [verlassen sich stark auf Überschriften](https://webaim.org/projects/screenreadersurvey8/#finding), um Informationen zu finden und durch eine Seite zu navigieren. Das Schreiben beschreibender Überschrifteninhalte und die Verwendung semantischer Überschriften-Tags sind wichtig, um eine leicht navigierbare Seite für Screenreader-Nutzer zu erstellen.
|
||||
|
||||
### Verwenden Sie gute visuelle Hinweise
|
||||
|
||||
CSS bietet vollständige Kontrolle über das Aussehen jedes Elements auf einer Seite. Sie können Textfelder ohne Umrandung oder Hyperlinks ohne Unterstreichung erstellen. Leider kann das Entfernen dieser Hinweise es für jemanden, der darauf angewiesen ist, schwieriger machen, die Art der Steuerung zu erkennen.
|
||||
|
||||
## Die Bedeutung von Linktext
|
||||
|
||||
Hyperlinks sind zentral für die Navigation im Web. Daher ist es wichtig, dass ein Screenreader Links korrekt lesen kann, damit alle Nutzer Ihre Website navigieren können.
|
||||
|
||||
### Screenreader und Links
|
||||
|
||||
Wie Sie erwarten würden, lesen Screenreader Linktext genauso wie jeden anderen Text auf der Seite. Mit diesem Wissen könnte der unten gezeigte Text akzeptabel erscheinen.
|
||||
|
||||
> Der kleine Pinguin, manchmal auch als Feenpinguin bekannt, ist der kleinste Pinguin der Welt. [Hier klicken](https://en.wikipedia.org/wiki/Little_penguin) für weitere Informationen.
|
||||
|
||||
> Der kleine Pinguin, manchmal auch als Feenpinguin bekannt, ist der kleinste Pinguin der Welt. Besuchen Sie https://en.wikipedia.org/wiki/Little_penguin für weitere Informationen.
|
||||
|
||||
> **NOTE** Wie Sie gleich lesen werden, sollten Sie **niemals** Links erstellen, die wie die oben genannten aussehen.
|
||||
|
||||
Denken Sie daran, dass Screenreader eine andere Schnittstelle als Browser sind und über ein anderes Set an Funktionen verfügen.
|
||||
|
||||
### Das Problem mit der Verwendung der URL
|
||||
|
||||
Screenreader lesen den Text. Wenn eine URL im Text erscheint, wird der Screenreader die URL vorlesen. Im Allgemeinen vermittelt die URL keine sinnvollen Informationen und kann störend klingen. Sie haben dies möglicherweise erlebt, wenn Ihr Telefon jemals eine Textnachricht mit einer URL hörbar vorgelesen hat.
|
||||
|
||||
### Das Problem mit "Hier klicken"
|
||||
|
||||
Screenreader können auch nur die Hyperlinks auf einer Seite vorlesen, ähnlich wie eine sehende Person eine Seite nach Links durchsucht. Wenn der Linktext immer "Hier klicken" lautet, hört der Nutzer nur "Hier klicken, Hier klicken, Hier klicken, Hier klicken, Hier klicken, ..." Alle Links sind jetzt nicht mehr voneinander unterscheidbar.
|
||||
|
||||
### Guter Linktext
|
||||
|
||||
Guter Linktext beschreibt kurz, was sich hinter dem Link befindet. Im obigen Beispiel über kleine Pinguine führt der Link zur Wikipedia-Seite über die Art. Der Ausdruck *kleine Pinguine* wäre perfekter Linktext, da er klar macht, was jemand erfährt, wenn er auf den Link klickt - kleine Pinguine.
|
||||
|
||||
> Der [kleine Pinguin](https://en.wikipedia.org/wiki/Little_penguin), manchmal auch als Feenpinguin bekannt, ist der kleinste Pinguin der Welt.
|
||||
|
||||
✅ Surfen Sie ein paar Minuten im Web, um Seiten zu finden, die undurchsichtige Verlinkungsstrategien verwenden. Vergleichen Sie sie mit anderen, besser verlinkten Seiten. Was lernen Sie?
|
||||
|
||||
#### Hinweise für Suchmaschinen
|
||||
|
||||
Als zusätzlicher Vorteil, wenn Sie sicherstellen, dass Ihre Website für alle zugänglich ist, helfen Sie auch Suchmaschinen, Ihre Website zu navigieren. Suchmaschinen verwenden Linktext, um die Themen von Seiten zu verstehen. Das Verwenden von gutem Linktext hilft also allen!
|
||||
|
||||
### ARIA
|
||||
|
||||
Stellen Sie sich die folgende Seite vor:
|
||||
|
||||
| Produkt | Beschreibung | Bestellung |
|
||||
| ------------ | ------------------ | ------------ |
|
||||
| Widget | [Beschreibung](../../../../1-getting-started-lessons/3-accessibility/') | [Bestellen](../../../../1-getting-started-lessons/3-accessibility/') |
|
||||
| Super Widget | [Beschreibung](../../../../1-getting-started-lessons/3-accessibility/') | [Bestellen](../../../../1-getting-started-lessons/3-accessibility/') |
|
||||
|
||||
In diesem Beispiel macht es für jemanden, der einen Browser verwendet, Sinn, den Text von Beschreibung und Bestellung zu duplizieren. Allerdings würde jemand, der einen Screenreader verwendet, nur die Wörter *Beschreibung* und *Bestellung* wiederholt hören, ohne Kontext.
|
||||
|
||||
Um solche Szenarien zu unterstützen, unterstützt HTML eine Reihe von Attributen, die als [Accessible Rich Internet Applications (ARIA)](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) bekannt sind. Diese Attribute ermöglichen es Ihnen, Screenreadern zusätzliche Informationen bereitzustellen.
|
||||
|
||||
> **NOTE**: Wie viele Aspekte von HTML kann die Unterstützung durch Browser und Screenreader variieren. Die meisten gängigen Clients unterstützen jedoch ARIA-Attribute.
|
||||
|
||||
Sie können `aria-label` verwenden, um den Link zu beschreiben, wenn das Format der Seite dies nicht zulässt. Die Beschreibung für Widget könnte wie folgt festgelegt werden:
|
||||
|
||||
``` html
|
||||
<a href="#" aria-label="Widget description">description</a>
|
||||
```
|
||||
|
||||
✅ Im Allgemeinen übertrifft die Verwendung von semantischem Markup wie oben beschrieben die Verwendung von ARIA, aber manchmal gibt es keine semantische Entsprechung für verschiedene HTML-Widgets. Ein gutes Beispiel ist ein Baum. Es gibt keine HTML-Entsprechung für einen Baum, daher identifizieren Sie das generische `<div>` für dieses Element mit einer passenden Rolle und ARIA-Werten. Die [MDN-Dokumentation zu ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) enthält weitere nützliche Informationen.
|
||||
|
||||
```html
|
||||
<h2 id="tree-label">File Viewer</h2>
|
||||
<div role="tree" aria-labelledby="tree-label">
|
||||
<div role="treeitem" aria-expanded="false" tabindex="0">Uploads</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Bilder
|
||||
|
||||
Es versteht sich von selbst, dass Screenreader nicht automatisch lesen können, was in einem Bild enthalten ist. Sicherzustellen, dass Bilder barrierefrei sind, erfordert nicht viel Arbeit - dafür ist das `alt`-Attribut da. Alle bedeutungsvollen Bilder sollten ein `alt` haben, um zu beschreiben, was sie sind. Bilder, die rein dekorativ sind, sollten ihr `alt`-Attribut auf einen leeren String setzen: `alt=""`. Dies verhindert, dass Screenreader das dekorative Bild unnötig ankündigen.
|
||||
|
||||
✅ Wie Sie vielleicht erwarten, können Suchmaschinen auch nicht verstehen, was in einem Bild enthalten ist. Sie verwenden ebenfalls Alt-Text. Daher bietet das Sicherstellen der Barrierefreiheit Ihrer Seite zusätzliche Vorteile!
|
||||
|
||||
## Die Tastatur
|
||||
|
||||
Einige Nutzer können keine Maus oder kein Trackpad verwenden und sind stattdessen auf Tastaturinteraktionen angewiesen, um von einem Element zum nächsten zu wechseln. Es ist wichtig, dass Ihre Website Ihre Inhalte in logischer Reihenfolge präsentiert, damit ein Tastaturnutzer jedes interaktive Element erreichen kann, während er ein Dokument durchgeht. Wenn Sie Ihre Webseiten mit semantischem Markup erstellen und CSS verwenden, um deren visuelles Layout zu gestalten, sollte Ihre Website mit der Tastatur navigierbar sein. Es ist jedoch wichtig, diesen Aspekt manuell zu testen. Erfahren Sie mehr über [Strategien zur Tastaturnavigation](https://webaim.org/techniques/keyboard/).
|
||||
|
||||
✅ Gehen Sie zu einer beliebigen Website und versuchen Sie, nur mit Ihrer Tastatur durch sie zu navigieren. Was funktioniert, was funktioniert nicht? Warum?
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
Ein Web, das nur für einige zugänglich ist, ist kein wirkliches 'World Wide Web'. Der beste Weg, um sicherzustellen, dass die von Ihnen erstellten Seiten barrierefrei sind, besteht darin, Barrierefreiheits-Best Practices von Anfang an zu integrieren. Während zusätzliche Schritte erforderlich sind, bedeutet das Einbinden dieser Fähigkeiten in Ihren Workflow jetzt, dass alle Seiten, die Sie erstellen, barrierefrei sein werden.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Nehmen Sie dieses HTML und schreiben Sie es so um, dass es so barrierefrei wie möglich ist, basierend auf den Strategien, die Sie gelernt haben.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Example
|
||||
</title>
|
||||
<link href='../assets/style.css' rel='stylesheet' type='text/css'>
|
||||
</head>
|
||||
<body>
|
||||
<div class="site-header">
|
||||
<p class="site-title">Turtle Ipsum</p>
|
||||
<p class="site-subtitle">The World's Premier Turtle Fan Club</p>
|
||||
</div>
|
||||
<div class="main-nav">
|
||||
<p class="nav-header">Resources</p>
|
||||
<div class="nav-list">
|
||||
<p class="nav-item nav-item-bull"><a href="https://www.youtube.com/watch?v=CMNry4PE93Y">"I like turtles"</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="https://en.wikipedia.org/wiki/Turtle">Basic Turtle Info</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="https://en.wikipedia.org/wiki/Turtles_(chocolate)">Chocolate Turtles</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div>
|
||||
<p class="page-title">Welcome to Turtle Ipsum.
|
||||
<a href="">Click here</a> to learn more.
|
||||
</p>
|
||||
<p class="article-text">
|
||||
Turtle ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="footer-section">
|
||||
<span class="button">Sign up for turtle news</span>
|
||||
</div><div class="footer-section">
|
||||
<p class="nav-header footer-title">
|
||||
Internal Pages
|
||||
</p>
|
||||
<div class="nav-list">
|
||||
<p class="nav-item nav-item-bull"><a href="../">Index</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="../semantic">Semantic Example</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="footer-copyright">© 2016 Instrument</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/6)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
Viele Regierungen haben Gesetze zu Barrierefreiheitsanforderungen. Informiere dich über die Barrierefreiheitsgesetze in deinem Heimatland. Was wird abgedeckt und was nicht? Ein Beispiel ist [diese Regierungswebseite](https://accessibility.blog.gov.uk/).
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Analysiere eine nicht barrierefreie Webseite](assignment.md)
|
||||
|
||||
Credits: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) von Instrument
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,26 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "a258597a194e77d4fd469b3cd976b29e",
|
||||
"translation_date": "2025-08-24T12:57:07+00:00",
|
||||
"source_file": "1-getting-started-lessons/3-accessibility/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Analysiere eine nicht barrierefreie Website
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Identifizieren Sie eine Website, von der Sie glauben, dass sie NICHT barrierefrei ist, und erstellen Sie einen Aktionsplan, um ihre Barrierefreiheit zu verbessern. Ihre erste Aufgabe besteht darin, diese Website zu identifizieren, die Gründe für ihre mangelnde Barrierefreiheit ohne analytische Tools zu beschreiben und sie anschließend einer Lighthouse-Analyse zu unterziehen. Erfassen Sie ein PDF der Ergebnisse dieser Analyse und erstellen Sie einen detaillierten Plan mit mindestens zehn Punkten, wie die Website verbessert werden könnte.
|
||||
|
||||
## Tabelle zur Überprüfung der Barrierefreiheit der Website
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungsbedarf |
|
||||
|-----------|-------------|------------|---------------------|
|
||||
| | weniger als 10 % der Anforderungen fehlen | 20 % der Anforderungen fehlen | 50 % der Anforderungen fehlen |
|
||||
|
||||
----
|
||||
Studentenbericht: enthält Absätze darüber, wie unzugänglich die Website ist, den Lighthouse-Bericht als PDF, eine Liste mit zehn Punkten zur Verbesserung sowie Details, wie diese Verbesserungen umgesetzt werden können
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,29 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "04683f4cfa46004179b0404b89a3065c",
|
||||
"translation_date": "2025-08-24T12:46:22+00:00",
|
||||
"source_file": "1-getting-started-lessons/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Einstieg in die Webentwicklung
|
||||
|
||||
In diesem Abschnitt des Lehrplans wirst du mit nicht projektbezogenen Konzepten vertraut gemacht, die wichtig sind, um ein professioneller Entwickler zu werden.
|
||||
|
||||
### Themen
|
||||
|
||||
1. [Einführung in Programmiersprachen und Werkzeuge des Handwerks](1-intro-to-programming-languages/README.md)
|
||||
2. [Einführung in GitHub](2-github-basics/README.md)
|
||||
3. [Grundlagen der Barrierefreiheit](3-accessibility/README.md)
|
||||
|
||||
### Danksagungen
|
||||
|
||||
Die Einführung in Programmiersprachen und Werkzeuge des Handwerks wurde mit ♥️ von [Jasmine Greenaway](https://twitter.com/paladique) geschrieben.
|
||||
|
||||
Die Einführung in GitHub wurde mit ♥️ von [Floor Drees](https://twitter.com/floordrees) geschrieben.
|
||||
|
||||
Die Grundlagen der Barrierefreiheit wurden mit ♥️ von [Christopher Harrison](https://twitter.com/geektrainer) geschrieben.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,213 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "fc6aef8ecfdd5b0ad2afa6e6ba52bfde",
|
||||
"translation_date": "2025-08-24T12:21:59+00:00",
|
||||
"source_file": "2-js-basics/1-data-types/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# JavaScript Grundlagen: Datentypen
|
||||
|
||||

|
||||
> Sketchnote von [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Quiz vor der Lektion
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/7)
|
||||
|
||||
Diese Lektion behandelt die Grundlagen von JavaScript, der Sprache, die Interaktivität im Web ermöglicht.
|
||||
|
||||
> Du kannst diese Lektion auf [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-variables/?WT.mc_id=academic-77807-sagibbon) absolvieren!
|
||||
|
||||
[](https://youtube.com/watch?v=JNIXfGiDWM8 "Variablen in JavaScript")
|
||||
|
||||
[](https://youtube.com/watch?v=AWfA95eLdq8 "Datentypen in JavaScript")
|
||||
|
||||
> 🎥 Klicke auf die Bilder oben, um Videos über Variablen und Datentypen anzusehen.
|
||||
|
||||
Lass uns mit Variablen und den Datentypen beginnen, die sie enthalten können!
|
||||
|
||||
## Variablen
|
||||
|
||||
Variablen speichern Werte, die in deinem Code verwendet und geändert werden können.
|
||||
|
||||
Das Erstellen und **Deklarieren** einer Variablen hat die folgende Syntax **[Schlüsselwort] [Name]**. Es besteht aus zwei Teilen:
|
||||
|
||||
- **Schlüsselwort**. Schlüsselwörter können `let` oder `var` sein.
|
||||
|
||||
✅ Das Schlüsselwort `let` wurde in ES6 eingeführt und gibt deiner Variablen einen sogenannten _Block Scope_. Es wird empfohlen, `let` anstelle von `var` zu verwenden. Wir werden Block Scopes später ausführlicher behandeln.
|
||||
- **Der Variablenname**, den du selbst auswählst.
|
||||
|
||||
### Aufgabe - Arbeiten mit Variablen
|
||||
|
||||
1. **Deklariere eine Variable**. Deklariere eine Variable mit dem Schlüsselwort `let`:
|
||||
|
||||
```javascript
|
||||
let myVariable;
|
||||
```
|
||||
|
||||
`myVariable` wurde nun mit dem Schlüsselwort `let` deklariert. Es hat derzeit keinen Wert.
|
||||
|
||||
1. **Weise einen Wert zu**. Speichere einen Wert in einer Variablen mit dem `=`-Operator, gefolgt vom gewünschten Wert.
|
||||
|
||||
```javascript
|
||||
myVariable = 123;
|
||||
```
|
||||
|
||||
> Hinweis: Die Verwendung von `=` in dieser Lektion bedeutet, dass wir einen "Zuweisungsoperator" verwenden, um einer Variablen einen Wert zuzuweisen. Es bedeutet nicht Gleichheit.
|
||||
|
||||
`myVariable` wurde nun mit dem Wert 123 *initialisiert*.
|
||||
|
||||
1. **Refaktorieren**. Ersetze deinen Code durch die folgende Anweisung.
|
||||
|
||||
```javascript
|
||||
let myVariable = 123;
|
||||
```
|
||||
|
||||
Das oben genannte wird als _explizite Initialisierung_ bezeichnet, wenn eine Variable deklariert und gleichzeitig ein Wert zugewiesen wird.
|
||||
|
||||
1. **Ändere den Variablenwert**. Ändere den Variablenwert auf folgende Weise:
|
||||
|
||||
```javascript
|
||||
myVariable = 321;
|
||||
```
|
||||
|
||||
Sobald eine Variable deklariert ist, kannst du ihren Wert jederzeit in deinem Code mit dem `=`-Operator und dem neuen Wert ändern.
|
||||
|
||||
✅ Probier es aus! Du kannst JavaScript direkt in deinem Browser schreiben. Öffne ein Browserfenster und navigiere zu den Entwicklertools. Im Konsolenbereich findest du eine Eingabeaufforderung; gib `let myVariable = 123` ein, drücke Enter und gib dann `myVariable` ein. Was passiert? Hinweis: Du wirst mehr über diese Konzepte in den folgenden Lektionen lernen.
|
||||
|
||||
## Konstanten
|
||||
|
||||
Die Deklaration und Initialisierung einer Konstante folgt denselben Konzepten wie bei einer Variablen, mit der Ausnahme des Schlüsselworts `const`. Konstanten werden typischerweise mit Großbuchstaben deklariert.
|
||||
|
||||
```javascript
|
||||
const MY_VARIABLE = 123;
|
||||
```
|
||||
|
||||
Konstanten sind ähnlich wie Variablen, mit zwei Ausnahmen:
|
||||
|
||||
- **Muss einen Wert haben**. Konstanten müssen initialisiert werden, sonst tritt ein Fehler auf, wenn der Code ausgeführt wird.
|
||||
- **Referenz kann nicht geändert werden**. Die Referenz einer Konstante kann nach der Initialisierung nicht geändert werden, sonst tritt ein Fehler auf, wenn der Code ausgeführt wird. Schauen wir uns zwei Beispiele an:
|
||||
- **Einfacher Wert**. Das Folgende ist NICHT erlaubt:
|
||||
|
||||
```javascript
|
||||
const PI = 3;
|
||||
PI = 4; // not allowed
|
||||
```
|
||||
|
||||
- **Objektreferenz ist geschützt**. Das Folgende ist NICHT erlaubt.
|
||||
|
||||
```javascript
|
||||
const obj = { a: 3 };
|
||||
obj = { b: 5 } // not allowed
|
||||
```
|
||||
|
||||
- **Objektwert ist nicht geschützt**. Das Folgende IST erlaubt:
|
||||
|
||||
```javascript
|
||||
const obj = { a: 3 };
|
||||
obj.a = 5; // allowed
|
||||
```
|
||||
|
||||
Oben änderst du den Wert des Objekts, aber nicht die Referenz selbst, was erlaubt ist.
|
||||
|
||||
> Hinweis: Ein `const` bedeutet, dass die Referenz vor einer Neuzuweisung geschützt ist. Der Wert ist jedoch nicht _unveränderlich_ und kann sich ändern, insbesondere wenn es sich um eine komplexe Struktur wie ein Objekt handelt.
|
||||
|
||||
## Datentypen
|
||||
|
||||
Variablen können viele verschiedene Arten von Werten speichern, wie Zahlen und Text. Diese verschiedenen Arten von Werten werden als **Datentyp** bezeichnet. Datentypen sind ein wichtiger Bestandteil der Softwareentwicklung, da sie Entwicklern helfen, Entscheidungen darüber zu treffen, wie der Code geschrieben und wie die Software ausgeführt werden soll. Darüber hinaus haben einige Datentypen einzigartige Eigenschaften, die helfen, zusätzliche Informationen aus einem Wert zu extrahieren oder ihn zu transformieren.
|
||||
|
||||
✅ Datentypen werden auch als JavaScript-Datenprimitiven bezeichnet, da sie die niedrigsten Datentypen sind, die von der Sprache bereitgestellt werden. Es gibt 7 primitive Datentypen: string, number, bigint, boolean, undefined, null und symbol. Nimm dir einen Moment Zeit, um dir vorzustellen, was jeder dieser Primitiven darstellen könnte. Was ist ein `zebra`? Wie wäre es mit `0`? `true`?
|
||||
|
||||
### Zahlen
|
||||
|
||||
Im vorherigen Abschnitt war der Wert von `myVariable` ein Zahlendatentyp.
|
||||
|
||||
`let myVariable = 123;`
|
||||
|
||||
Variablen können alle Arten von Zahlen speichern, einschließlich Dezimalzahlen oder negativer Zahlen. Zahlen können auch mit arithmetischen Operatoren verwendet werden, die im [nächsten Abschnitt](../../../../2-js-basics/1-data-types) behandelt werden.
|
||||
|
||||
### Arithmetische Operatoren
|
||||
|
||||
Es gibt verschiedene Arten von Operatoren, die bei der Durchführung arithmetischer Funktionen verwendet werden können, und einige sind hier aufgeführt:
|
||||
|
||||
| Symbol | Beschreibung | Beispiel |
|
||||
| ------ | ------------------------------------------------------------------------ | -------------------------------- |
|
||||
| `+` | **Addition**: Berechnet die Summe von zwei Zahlen | `1 + 2 //erwartete Antwort ist 3` |
|
||||
| `-` | **Subtraktion**: Berechnet die Differenz von zwei Zahlen | `1 - 2 //erwartete Antwort ist -1` |
|
||||
| `*` | **Multiplikation**: Berechnet das Produkt von zwei Zahlen | `1 * 2 //erwartete Antwort ist 2` |
|
||||
| `/` | **Division**: Berechnet den Quotienten von zwei Zahlen | `1 / 2 //erwartete Antwort ist 0.5` |
|
||||
| `%` | **Rest**: Berechnet den Rest der Division von zwei Zahlen | `1 % 2 //erwartete Antwort ist 1` |
|
||||
|
||||
✅ Probier es aus! Probiere eine arithmetische Operation in der Konsole deines Browsers aus. Überraschen dich die Ergebnisse?
|
||||
|
||||
### Strings
|
||||
|
||||
Strings sind Zeichenfolgen, die zwischen einfachen oder doppelten Anführungszeichen stehen.
|
||||
|
||||
- `'Das ist ein String'`
|
||||
- `"Das ist auch ein String"`
|
||||
- `let myString = 'Das ist ein Stringwert, der in einer Variablen gespeichert ist';`
|
||||
|
||||
Denke daran, Anführungszeichen zu verwenden, wenn du einen String schreibst, sonst nimmt JavaScript an, dass es sich um einen Variablennamen handelt.
|
||||
|
||||
### Strings formatieren
|
||||
|
||||
Strings sind textuell und müssen von Zeit zu Zeit formatiert werden.
|
||||
|
||||
Um zwei oder mehr Strings zu **konkatenieren**, also zusammenzufügen, verwende den `+`-Operator.
|
||||
|
||||
```javascript
|
||||
let myString1 = "Hello";
|
||||
let myString2 = "World";
|
||||
|
||||
myString1 + myString2 + "!"; //HelloWorld!
|
||||
myString1 + " " + myString2 + "!"; //Hello World!
|
||||
myString1 + ", " + myString2 + "!"; //Hello, World!
|
||||
|
||||
```
|
||||
|
||||
✅ Warum ergibt `1 + 1 = 2` in JavaScript, aber `'1' + '1' = 11`? Denk darüber nach. Was ist mit `'1' + 1`?
|
||||
|
||||
**Template Literals** sind eine andere Möglichkeit, Strings zu formatieren. Statt Anführungszeichen wird hier das Backtick verwendet. Alles, was kein reiner Text ist, muss in Platzhalter `${ }` gesetzt werden. Dazu gehören auch Variablen, die Strings sein können.
|
||||
|
||||
```javascript
|
||||
let myString1 = "Hello";
|
||||
let myString2 = "World";
|
||||
|
||||
`${myString1} ${myString2}!` //Hello World!
|
||||
`${myString1}, ${myString2}!` //Hello, World!
|
||||
```
|
||||
|
||||
Du kannst deine Formatierungsziele mit beiden Methoden erreichen, aber Template Literals respektieren alle Leerzeichen und Zeilenumbrüche.
|
||||
|
||||
✅ Wann würdest du ein Template Literal gegenüber einem einfachen String verwenden?
|
||||
|
||||
### Booleans
|
||||
|
||||
Booleans können nur zwei Werte haben: `true` oder `false`. Booleans können helfen, Entscheidungen darüber zu treffen, welche Codezeilen ausgeführt werden sollen, wenn bestimmte Bedingungen erfüllt sind. In vielen Fällen helfen [Operatoren](../../../../2-js-basics/1-data-types) dabei, den Wert eines Booleans festzulegen, und du wirst oft Variablen bemerken und schreiben, die initialisiert werden oder deren Werte mit einem Operator aktualisiert werden.
|
||||
|
||||
- `let myTrueBool = true`
|
||||
- `let myFalseBool = false`
|
||||
|
||||
✅ Eine Variable kann als 'truthy' betrachtet werden, wenn sie zu einem Boolean `true` ausgewertet wird. Interessanterweise sind in JavaScript [alle Werte truthy, es sei denn, sie sind als falsy definiert](https://developer.mozilla.org/docs/Glossary/Truthy).
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
JavaScript ist berüchtigt für seine gelegentlich überraschenden Arten, Datentypen zu behandeln. Recherchiere ein wenig über diese 'Fallstricke'. Zum Beispiel: Groß- und Kleinschreibung kann problematisch sein! Probiere dies in deiner Konsole: `let age = 1; let Age = 2; age == Age` (ergibt `false` -- warum?). Welche anderen Fallstricke kannst du finden?
|
||||
|
||||
## Quiz nach der Lektion
|
||||
[Quiz nach der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/8)
|
||||
|
||||
## Wiederholung & Selbststudium
|
||||
|
||||
Schau dir [diese Liste von JavaScript-Übungen](https://css-tricks.com/snippets/javascript/) an und probiere eine aus. Was hast du gelernt?
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Übung zu Datentypen](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "3869244ceda606c4969d8cdd82679867",
|
||||
"translation_date": "2025-08-24T12:24:05+00:00",
|
||||
"source_file": "2-js-basics/1-data-types/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Übung zu Datentypen
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Stellen Sie sich vor, Sie erstellen einen Einkaufswagen. Schreiben Sie eine Dokumentation über die Datentypen, die Sie benötigen, um Ihr Einkaufserlebnis abzuschließen. Wie sind Sie zu Ihren Entscheidungen gekommen?
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig
|
||||
--- | --- | --- | --- |
|
||||
||Die sechs Datentypen werden aufgelistet und ausführlich untersucht, ihre Verwendung wird dokumentiert|Vier Datentypen werden untersucht|Zwei Datentypen werden untersucht|
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "8973f96157680a13e9446e4bb540ee57",
|
||||
"translation_date": "2025-08-24T12:18:17+00:00",
|
||||
"source_file": "2-js-basics/2-functions-methods/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Spaß mit Funktionen
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Erstelle verschiedene Funktionen, sowohl solche, die etwas zurückgeben, als auch solche, die nichts zurückgeben.
|
||||
|
||||
Versuche, eine Funktion zu erstellen, die eine Mischung aus Parametern und Parametern mit Standardwerten enthält.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------- |
|
||||
| | Es werden zwei oder mehr gut funktionierende Funktionen mit vielfältigen Parametern angeboten | Es wird eine funktionierende Lösung mit einer Funktion und wenigen Parametern angeboten | Die Lösung enthält Fehler |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,52 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "bf62b82567e6f9bdf4abda9ae0ccb64a",
|
||||
"translation_date": "2025-08-24T12:14:55+00:00",
|
||||
"source_file": "2-js-basics/3-making-decisions/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Operatoren
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Experimentiere mit Operatoren. Hier ist ein Vorschlag für ein Programm, das du implementieren kannst:
|
||||
|
||||
Du hast eine Gruppe von Schülern aus zwei verschiedenen Notensystemen.
|
||||
|
||||
### Erstes Notensystem
|
||||
|
||||
Ein Notensystem definiert die Noten von 1-5, wobei 3 und höher bedeutet, dass man den Kurs besteht.
|
||||
|
||||
### Zweites Notensystem
|
||||
|
||||
Das andere Notensystem hat die folgenden Noten: `A, A-, B, B-, C, C-`, wobei `A` die beste Note ist und `C` die niedrigste Note, mit der man besteht.
|
||||
|
||||
### Die Aufgabe
|
||||
|
||||
Gegeben ist das folgende Array `allStudents`, das alle Schüler und ihre Noten repräsentiert. Erstelle ein neues Array `studentsWhoPass`, das alle Schüler enthält, die bestehen.
|
||||
|
||||
> TIP: Verwende eine for-Schleife, if...else und Vergleichsoperatoren:
|
||||
|
||||
```javascript
|
||||
let allStudents = [
|
||||
'A',
|
||||
'B-',
|
||||
1,
|
||||
4,
|
||||
5,
|
||||
2
|
||||
]
|
||||
|
||||
let studentsWhoPass = [];
|
||||
```
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ----------------------------- | ----------------------------- | ------------------------------- |
|
||||
| | Vollständige Lösung wird präsentiert | Teilweise Lösung wird präsentiert | Lösung mit Fehlern wird präsentiert |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,145 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "3f7f87871312cf6cc12662da7d973182",
|
||||
"translation_date": "2025-08-24T12:19:16+00:00",
|
||||
"source_file": "2-js-basics/4-arrays-loops/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# JavaScript-Grundlagen: Arrays und Schleifen
|
||||
|
||||

|
||||
> Sketchnote von [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Quiz vor der Lektion
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/13)
|
||||
|
||||
Diese Lektion behandelt die Grundlagen von JavaScript, der Sprache, die Interaktivität im Web ermöglicht. In dieser Lektion lernst du Arrays und Schleifen kennen, die zur Datenmanipulation verwendet werden.
|
||||
|
||||
[](https://youtube.com/watch?v=1U4qTyq02Xw "Arrays")
|
||||
|
||||
[](https://www.youtube.com/watch?v=Eeh7pxtTZ3k "Schleifen")
|
||||
|
||||
> 🎥 Klicke auf die Bilder oben, um Videos über Arrays und Schleifen anzusehen.
|
||||
|
||||
> Du kannst diese Lektion auf [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-arrays/?WT.mc_id=academic-77807-sagibbon) absolvieren!
|
||||
|
||||
## Arrays
|
||||
|
||||
Das Arbeiten mit Daten ist eine häufige Aufgabe in jeder Programmiersprache, und es ist viel einfacher, wenn Daten in einer strukturierten Form wie Arrays organisiert sind. Mit Arrays werden Daten in einer Struktur ähnlich einer Liste gespeichert. Ein großer Vorteil von Arrays ist, dass du verschiedene Datentypen in einem Array speichern kannst.
|
||||
|
||||
✅ Arrays sind überall um uns herum! Kannst du ein Beispiel aus dem echten Leben für ein Array nennen, wie etwa ein Solarpanel-Array?
|
||||
|
||||
Die Syntax für ein Array besteht aus einem Paar eckiger Klammern.
|
||||
|
||||
```javascript
|
||||
let myArray = [];
|
||||
```
|
||||
|
||||
Dies ist ein leeres Array, aber Arrays können auch direkt mit Daten gefüllt deklariert werden. Mehrere Werte in einem Array werden durch ein Komma getrennt.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
```
|
||||
|
||||
Die Array-Werte erhalten einen eindeutigen Wert, der **Index** genannt wird, eine ganze Zahl, die basierend auf ihrer Entfernung vom Anfang des Arrays zugewiesen wird. Im obigen Beispiel hat der String-Wert "Chocolate" einen Index von 0, und der Index von "Rocky Road" ist 4. Verwende den Index mit eckigen Klammern, um Array-Werte abzurufen, zu ändern oder einzufügen.
|
||||
|
||||
✅ Überrascht es dich, dass Arrays beim Index 0 beginnen? In einigen Programmiersprachen beginnen Indizes bei 1. Es gibt eine interessante Geschichte dazu, die du [auf Wikipedia lesen kannst](https://en.wikipedia.org/wiki/Zero-based_numbering).
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
iceCreamFlavors[2]; //"Vanilla"
|
||||
```
|
||||
|
||||
Du kannst den Index nutzen, um einen Wert zu ändern, so wie hier:
|
||||
|
||||
```javascript
|
||||
iceCreamFlavors[4] = "Butter Pecan"; //Changed "Rocky Road" to "Butter Pecan"
|
||||
```
|
||||
|
||||
Und du kannst einen neuen Wert an einem bestimmten Index einfügen, so wie hier:
|
||||
|
||||
```javascript
|
||||
iceCreamFlavors[5] = "Cookie Dough"; //Added "Cookie Dough"
|
||||
```
|
||||
|
||||
✅ Eine häufigere Methode, Werte zu einem Array hinzuzufügen, ist die Verwendung von Array-Operatoren wie array.push()
|
||||
|
||||
Um herauszufinden, wie viele Elemente sich in einem Array befinden, verwende die `length`-Eigenschaft.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
iceCreamFlavors.length; //5
|
||||
```
|
||||
|
||||
✅ Probier es selbst aus! Erstelle und manipuliere ein Array deiner Wahl in der Konsole deines Browsers.
|
||||
|
||||
## Schleifen
|
||||
|
||||
Schleifen ermöglichen es uns, repetitive oder **iterative** Aufgaben auszuführen, und können viel Zeit und Code sparen. Jede Iteration kann sich in ihren Variablen, Werten und Bedingungen unterscheiden. Es gibt verschiedene Arten von Schleifen in JavaScript, die alle kleine Unterschiede aufweisen, aber im Wesentlichen dasselbe tun: über Daten iterieren.
|
||||
|
||||
### For-Schleife
|
||||
|
||||
Die `for`-Schleife benötigt 3 Teile, um zu iterieren:
|
||||
- `counter` Eine Variable, die typischerweise mit einer Zahl initialisiert wird, die die Anzahl der Iterationen zählt
|
||||
- `condition` Ausdruck, der Vergleichsoperatoren verwendet, um die Schleife zu stoppen, wenn `false`
|
||||
- `iteration-expression` Wird am Ende jeder Iteration ausgeführt, typischerweise verwendet, um den Zählerwert zu ändern
|
||||
|
||||
```javascript
|
||||
// Counting up to 10
|
||||
for (let i = 0; i < 10; i++) {
|
||||
console.log(i);
|
||||
}
|
||||
```
|
||||
|
||||
✅ Führe diesen Code in der Konsole deines Browsers aus. Was passiert, wenn du kleine Änderungen am Zähler, der Bedingung oder dem Iterationsausdruck vornimmst? Kannst du die Schleife rückwärts laufen lassen, um einen Countdown zu erstellen?
|
||||
|
||||
### While-Schleife
|
||||
|
||||
Im Gegensatz zur Syntax der `for`-Schleife benötigen `while`-Schleifen nur eine Bedingung, die die Schleife stoppt, wenn die Bedingung `false` wird. Bedingungen in Schleifen hängen normalerweise von anderen Werten wie Zählern ab und müssen während der Schleife verwaltet werden. Startwerte für Zähler müssen außerhalb der Schleife erstellt werden, und alle Ausdrücke, die eine Bedingung erfüllen, einschließlich der Änderung des Zählers, müssen innerhalb der Schleife gepflegt werden.
|
||||
|
||||
```javascript
|
||||
//Counting up to 10
|
||||
let i = 0;
|
||||
while (i < 10) {
|
||||
console.log(i);
|
||||
i++;
|
||||
}
|
||||
```
|
||||
|
||||
✅ Warum würdest du eine for-Schleife gegenüber einer while-Schleife wählen? 17.000 Nutzer hatten dieselbe Frage auf StackOverflow, und einige der Meinungen [könnten für dich interessant sein](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
|
||||
|
||||
## Schleifen und Arrays
|
||||
|
||||
Arrays werden oft mit Schleifen verwendet, da die meisten Bedingungen die Länge des Arrays benötigen, um die Schleife zu stoppen, und der Index auch als Zählerwert dienen kann.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
|
||||
for (let i = 0; i < iceCreamFlavors.length; i++) {
|
||||
console.log(iceCreamFlavors[i]);
|
||||
} //Ends when all flavors are printed
|
||||
```
|
||||
|
||||
✅ Experimentiere mit dem Iterieren über ein Array deiner Wahl in der Konsole deines Browsers.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Es gibt andere Möglichkeiten, über Arrays zu iterieren, außer mit for- und while-Schleifen. Es gibt [forEach](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), [for-of](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for...of) und [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Schreibe deine Array-Schleife mit einer dieser Techniken um.
|
||||
|
||||
## Quiz nach der Lektion
|
||||
[Quiz nach der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/14)
|
||||
|
||||
## Wiederholung & Selbststudium
|
||||
|
||||
Arrays in JavaScript haben viele Methoden, die äußerst nützlich für die Datenmanipulation sind. [Lies mehr über diese Methoden](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) und probiere einige davon aus (wie push, pop, slice und splice) an einem Array deiner Wahl.
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Iteriere über ein Array](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "8b2381170bd0fd2870f5889bb8620f02",
|
||||
"translation_date": "2025-08-24T12:20:50+00:00",
|
||||
"source_file": "2-js-basics/4-arrays-loops/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Ein Array durchlaufen
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Erstelle ein Programm, das jede 3. Zahl zwischen 1 und 20 auflistet und in der Konsole ausgibt.
|
||||
|
||||
> TIP: Verwende eine for-Schleife und passe den Iterationsausdruck an.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterium | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | --------------------------------------- | ------------------------ | ------------------------------ |
|
||||
| | Programm läuft korrekt und ist kommentiert | Programm ist nicht kommentiert | Programm ist unvollständig oder fehlerhaft |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,26 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "cc9e70a2f096c67389c8acff1521fc27",
|
||||
"translation_date": "2025-08-24T12:11:56+00:00",
|
||||
"source_file": "2-js-basics/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Einführung in JavaScript
|
||||
|
||||
JavaScript ist die Sprache des Webs. In diesen vier Lektionen lernst du die Grundlagen.
|
||||
|
||||
### Themen
|
||||
|
||||
1. [Variablen und Datentypen](1-data-types/README.md)
|
||||
2. [Funktionen und Methoden](2-functions-methods/README.md)
|
||||
3. [Entscheidungen treffen mit JavaScript](3-making-decisions/README.md)
|
||||
4. [Arrays und Schleifen](4-arrays-loops/README.md)
|
||||
|
||||
### Credits
|
||||
|
||||
Diese Lektionen wurden mit ♥️ geschrieben von [Jasmine Greenaway](https://twitter.com/paladique), [Christopher Harrison](https://twitter.com/geektrainer) und [Chris Noring](https://twitter.com/chris_noring)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,247 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "46a0639e719b9cf1dfd062aa24cad639",
|
||||
"translation_date": "2025-08-24T12:00:14+00:00",
|
||||
"source_file": "3-terrarium/1-intro-to-html/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Terrarium-Projekt Teil 1: Einführung in HTML
|
||||
|
||||

|
||||
> Sketchnote von [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Quiz vor der Lektion
|
||||
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/15)
|
||||
|
||||
> Schau dir das Video an
|
||||
|
||||
>
|
||||
> [](https://www.youtube.com/watch?v=1TvxJKBzhyQ)
|
||||
|
||||
### Einführung
|
||||
|
||||
HTML, oder HyperText Markup Language, ist das 'Skelett' des Webs. Wenn CSS dein HTML 'anzieht' und JavaScript es zum Leben erweckt, dann ist HTML der Körper deiner Webanwendung. Die Syntax von HTML spiegelt diese Idee wider, da sie Tags wie "head", "body" und "footer" enthält.
|
||||
|
||||
In dieser Lektion werden wir HTML verwenden, um das 'Skelett' der Benutzeroberfläche unseres virtuellen Terrariums zu erstellen. Es wird einen Titel und drei Spalten haben: eine rechte und eine linke Spalte, in denen die verschiebbaren Pflanzen leben, und einen mittleren Bereich, der das eigentliche gläserne Terrarium darstellt. Am Ende dieser Lektion wirst du die Pflanzen in den Spalten sehen können, aber die Benutzeroberfläche wird noch etwas seltsam aussehen; keine Sorge, im nächsten Abschnitt wirst du CSS-Stile hinzufügen, um die Benutzeroberfläche ansprechender zu gestalten.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Erstelle auf deinem Computer einen Ordner namens 'terrarium' und darin eine Datei namens 'index.html'. Du kannst dies in Visual Studio Code tun, nachdem du deinen Terrarium-Ordner erstellt hast, indem du ein neues VS Code-Fenster öffnest, auf 'Ordner öffnen' klickst und zu deinem neuen Ordner navigierst. Klicke im Explorer-Bereich auf die kleine Schaltfläche 'Datei' und erstelle die neue Datei:
|
||||
|
||||

|
||||
|
||||
Oder
|
||||
|
||||
Verwende diese Befehle in deinem Git Bash:
|
||||
* `mkdir terrarium`
|
||||
* `cd terrarium`
|
||||
* `touch index.html`
|
||||
* `code index.html` oder `nano index.html`
|
||||
|
||||
> index.html-Dateien zeigen einem Browser an, dass es sich um die Standarddatei in einem Ordner handelt; URLs wie `https://anysite.com/test` könnten auf einer Ordnerstruktur basieren, die einen Ordner namens `test` mit einer `index.html`-Datei enthält; `index.html` muss nicht in der URL angezeigt werden.
|
||||
|
||||
---
|
||||
|
||||
## Der DocType und die html-Tags
|
||||
|
||||
Die erste Zeile einer HTML-Datei ist ihr Doctype. Es ist etwas überraschend, dass diese Zeile ganz oben in der Datei stehen muss, aber sie teilt älteren Browsern mit, dass die Seite im Standardmodus gerendert werden soll, der der aktuellen HTML-Spezifikation entspricht.
|
||||
|
||||
> Tipp: In VS Code kannst du über ein Tag fahren, um Informationen über dessen Verwendung aus den MDN-Referenzleitfäden zu erhalten.
|
||||
|
||||
Die zweite Zeile sollte das öffnende `<html>`-Tag sein, gefolgt von seinem schließenden Tag `</html>`. Diese Tags sind die Wurzelelemente deiner Benutzeroberfläche.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Füge diese Zeilen oben in deiner `index.html`-Datei hinzu:
|
||||
|
||||
```HTML
|
||||
<!DOCTYPE html>
|
||||
<html></html>
|
||||
```
|
||||
|
||||
✅ Es gibt einige verschiedene Modi, die durch das Festlegen des Doctype mit einer Abfragezeichenfolge bestimmt werden können: [Quirks Mode und Standards Mode](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode). Diese Modi dienten der Unterstützung wirklich alter Browser, die heutzutage normalerweise nicht mehr verwendet werden (Netscape Navigator 4 und Internet Explorer 5). Du kannst bei der Standard-Doctype-Deklaration bleiben.
|
||||
|
||||
---
|
||||
|
||||
## Der 'head' des Dokuments
|
||||
|
||||
Der 'head'-Bereich des HTML-Dokuments enthält wichtige Informationen über deine Webseite, auch bekannt als [Metadaten](https://developer.mozilla.org/docs/Web/HTML/Element/meta). In unserem Fall teilen wir dem Webserver, an den diese Seite gesendet wird, um gerendert zu werden, diese vier Dinge mit:
|
||||
|
||||
- den Titel der Seite
|
||||
- Metadaten der Seite, einschließlich:
|
||||
- des 'Zeichensatzes', der angibt, welche Zeichenkodierung auf der Seite verwendet wird
|
||||
- Browserinformationen, einschließlich `x-ua-compatible`, das angibt, dass der IE=edge-Browser unterstützt wird
|
||||
- Informationen darüber, wie das Viewport beim Laden reagieren soll. Das Festlegen des Viewports auf eine anfängliche Skalierung von 1 steuert den Zoomlevel, wenn die Seite zum ersten Mal geladen wird.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Füge einen 'head'-Block zu deinem Dokument zwischen den öffnenden und schließenden `<html>`-Tags hinzu.
|
||||
|
||||
```html
|
||||
<head>
|
||||
<title>Welcome to my Virtual Terrarium</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
```
|
||||
|
||||
✅ Was würde passieren, wenn du ein Viewport-Meta-Tag wie dieses festlegst: `<meta name="viewport" content="width=600">`? Lies mehr über das [Viewport](https://developer.mozilla.org/docs/Web/HTML/Viewport_meta_tag).
|
||||
|
||||
---
|
||||
|
||||
## Der `body` des Dokuments
|
||||
|
||||
### HTML-Tags
|
||||
|
||||
In HTML fügst du Tags zu deiner .html-Datei hinzu, um Elemente einer Webseite zu erstellen. Jedes Tag hat normalerweise ein öffnendes und ein schließendes Tag, wie dieses: `<p>hallo</p>`, um einen Absatz anzuzeigen. Erstelle den Body deiner Benutzeroberfläche, indem du ein Paar `<body>`-Tags innerhalb des `<html>`-Tag-Paares hinzufügst; dein Markup sieht jetzt so aus:
|
||||
|
||||
### Aufgabe
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to my Virtual Terrarium</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Jetzt kannst du anfangen, deine Seite zu erstellen. Normalerweise verwendest du `<div>`-Tags, um die separaten Elemente auf einer Seite zu erstellen. Wir werden eine Reihe von `<div>`-Elementen erstellen, die Bilder enthalten.
|
||||
|
||||
### Bilder
|
||||
|
||||
Ein HTML-Tag, das kein schließendes Tag benötigt, ist das `<img>`-Tag, da es ein `src`-Element hat, das alle Informationen enthält, die die Seite benötigt, um das Element zu rendern.
|
||||
|
||||
Erstelle einen Ordner in deiner App namens `images` und füge dort alle Bilder aus dem [Quellcode-Ordner](../../../../3-terrarium/solution/images) hinzu; (es gibt 14 Bilder von Pflanzen).
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Füge diese Pflanzenbilder in zwei Spalten zwischen den `<body></body>`-Tags ein:
|
||||
|
||||
```html
|
||||
<div id="page">
|
||||
<div id="left-container" class="container">
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant1" src="./images/plant1.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant2" src="./images/plant2.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant3" src="./images/plant3.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant4" src="./images/plant4.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant5" src="./images/plant5.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant6" src="./images/plant6.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant7" src="./images/plant7.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div id="right-container" class="container">
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant8" src="./images/plant8.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant9" src="./images/plant9.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant10" src="./images/plant10.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant11" src="./images/plant11.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant12" src="./images/plant12.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant13" src="./images/plant13.png" />
|
||||
</div>
|
||||
<div class="plant-holder">
|
||||
<img class="plant" alt="plant" id="plant14" src="./images/plant14.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
> Hinweis: Spans vs. Divs. Divs werden als 'Block'-Elemente betrachtet, und Spans sind 'Inline'-Elemente. Was würde passieren, wenn du diese Divs in Spans umwandelst?
|
||||
|
||||
Mit diesem Markup erscheinen die Pflanzen jetzt auf dem Bildschirm. Es sieht ziemlich schlecht aus, da sie noch nicht mit CSS gestylt sind, und das werden wir in der nächsten Lektion tun.
|
||||
|
||||
Jedes Bild hat einen Alt-Text, der angezeigt wird, auch wenn du ein Bild nicht sehen oder rendern kannst. Dies ist ein wichtiges Attribut, um die Barrierefreiheit zu gewährleisten. Erfahre mehr über Barrierefreiheit in zukünftigen Lektionen; für jetzt merke dir, dass das Alt-Attribut alternative Informationen für ein Bild bereitstellt, falls ein Benutzer das Bild aus irgendeinem Grund nicht sehen kann (aufgrund einer langsamen Verbindung, eines Fehlers im src-Attribut oder wenn der Benutzer einen Screenreader verwendet).
|
||||
|
||||
✅ Ist dir aufgefallen, dass jedes Bild denselben Alt-Tag hat? Ist das eine gute Praxis? Warum oder warum nicht? Kannst du diesen Code verbessern?
|
||||
|
||||
---
|
||||
|
||||
## Semantisches Markup
|
||||
|
||||
Im Allgemeinen ist es vorzuziehen, beim Schreiben von HTML sinnvolle 'Semantik' zu verwenden. Was bedeutet das? Es bedeutet, dass du HTML-Tags verwendest, um die Art der Daten oder Interaktionen darzustellen, für die sie entworfen wurden. Zum Beispiel sollte der Haupttiteltext auf einer Seite ein `<h1>`-Tag verwenden.
|
||||
|
||||
Füge die folgende Zeile direkt unter deinem öffnenden `<body>`-Tag hinzu:
|
||||
|
||||
```html
|
||||
<h1>My Terrarium</h1>
|
||||
```
|
||||
|
||||
Die Verwendung von semantischem Markup, wie das Verwenden von `<h1>` für Überschriften und `<ul>` für ungeordnete Listen, hilft Screenreadern, sich durch eine Seite zu navigieren. Im Allgemeinen sollten Schaltflächen als `<button>` geschrieben werden und Listen als `<li>`. Während es _möglich_ ist, speziell gestylte `<span>`-Elemente mit Klick-Handlern zu verwenden, um Schaltflächen zu imitieren, ist es für Benutzer mit Behinderungen besser, Technologien zu verwenden, um zu bestimmen, wo sich eine Schaltfläche auf einer Seite befindet, und mit ihr zu interagieren, wenn das Element als Schaltfläche erscheint. Aus diesem Grund solltest du so oft wie möglich semantisches Markup verwenden.
|
||||
|
||||
✅ Schau dir einen Screenreader an und [wie er mit einer Webseite interagiert](https://www.youtube.com/watch?v=OUDV1gqs9GA). Kannst du sehen, warum nicht-semantisches Markup den Benutzer frustrieren könnte?
|
||||
|
||||
## Das Terrarium
|
||||
|
||||
Der letzte Teil dieser Benutzeroberfläche besteht darin, ein Markup zu erstellen, das so gestylt wird, dass es ein Terrarium darstellt.
|
||||
|
||||
### Aufgabe:
|
||||
|
||||
Füge dieses Markup oberhalb des letzten `</div>`-Tags hinzu:
|
||||
|
||||
```html
|
||||
<div id="terrarium">
|
||||
<div class="jar-top"></div>
|
||||
<div class="jar-walls">
|
||||
<div class="jar-glossy-long"></div>
|
||||
<div class="jar-glossy-short"></div>
|
||||
</div>
|
||||
<div class="dirt"></div>
|
||||
<div class="jar-bottom"></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
✅ Obwohl du dieses Markup auf dem Bildschirm hinzugefügt hast, siehst du absolut nichts gerendert. Warum?
|
||||
|
||||
---
|
||||
|
||||
## 🚀Herausforderung
|
||||
|
||||
Es gibt einige wilde 'ältere' Tags in HTML, die immer noch Spaß machen, obwohl du veraltete Tags wie [diese Tags](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements) nicht in deinem Markup verwenden solltest. Kannst du trotzdem das alte `<marquee>`-Tag verwenden, um den h1-Titel horizontal scrollen zu lassen? (Falls du das machst, vergiss nicht, es danach zu entfernen.)
|
||||
|
||||
## Quiz nach der Lektion
|
||||
|
||||
[Quiz nach der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/16)
|
||||
|
||||
## Rückblick & Selbststudium
|
||||
|
||||
HTML ist das 'bewährte' Bausteinsystem, das dazu beigetragen hat, das Web zu dem zu machen, was es heute ist. Erfahre ein wenig über seine Geschichte, indem du einige alte und neue Tags studierst. Kannst du herausfinden, warum einige Tags veraltet und andere hinzugefügt wurden? Welche Tags könnten in Zukunft eingeführt werden?
|
||||
|
||||
Erfahre mehr über den Aufbau von Websites für das Web und mobile Geräte bei [Microsoft Learn](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Übe dein HTML: Erstelle ein Blog-Layout](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "9d4d75af51aaccfe9af778f792c62919",
|
||||
"translation_date": "2025-08-24T12:10:29+00:00",
|
||||
"source_file": "3-terrarium/2-intro-to-css/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# CSS-Refaktorierung
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Gestalte das Terrarium neu mit entweder Flexbox oder CSS Grid und mache Screenshots, um zu zeigen, dass du es in mehreren Browsern getestet hast. Es könnte notwendig sein, das Markup zu ändern, also erstelle eine neue Version der App mit der Kunst, die für deine Refaktorierung vorgesehen ist. Mach dir keine Sorgen darüber, die Elemente verschiebbar zu machen; refaktoriere vorerst nur das HTML und CSS.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ---------------------------------------------------------------- | ----------------------------- | ----------------------------------- |
|
||||
| | Ein vollständig neu gestaltetes Terrarium mit Flexbox oder CSS Grid präsentieren | Einige Elemente neu gestalten | Das Terrarium überhaupt nicht neu gestalten |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,231 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "30f8903a1f290e3d438dc2c70fe60259",
|
||||
"translation_date": "2025-08-24T12:04:01+00:00",
|
||||
"source_file": "3-terrarium/3-intro-to-DOM-and-closures/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Terrarium-Projekt Teil 3: DOM-Manipulation und eine Closure
|
||||
|
||||

|
||||
> Sketchnote von [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/19)
|
||||
|
||||
### Einführung
|
||||
|
||||
Die Manipulation des DOM, oder des "Document Object Model", ist ein zentraler Aspekt der Webentwicklung. Laut [MDN](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) ist "Das Document Object Model (DOM) die Datenrepräsentation der Objekte, die die Struktur und den Inhalt eines Dokuments im Web ausmachen." Die Herausforderungen rund um die DOM-Manipulation im Web haben oft dazu geführt, dass JavaScript-Frameworks anstelle von reinem JavaScript verwendet werden, um das DOM zu verwalten. Aber wir werden es selbst schaffen!
|
||||
|
||||
Darüber hinaus wird in dieser Lektion die Idee einer [JavaScript-Closure](https://developer.mozilla.org/docs/Web/JavaScript/Closures) eingeführt, die man sich als eine Funktion vorstellen kann, die von einer anderen Funktion umschlossen ist, sodass die innere Funktion Zugriff auf den Scope der äußeren Funktion hat.
|
||||
|
||||
> JavaScript-Closures sind ein umfangreiches und komplexes Thema. Diese Lektion behandelt die grundlegende Idee, dass im Code dieses Terrariums eine Closure vorkommt: eine innere Funktion und eine äußere Funktion, die so konstruiert sind, dass die innere Funktion Zugriff auf den Scope der äußeren Funktion hat. Für weitere Informationen darüber, wie dies funktioniert, besuchen Sie bitte die [ausführliche Dokumentation](https://developer.mozilla.org/docs/Web/JavaScript/Closures).
|
||||
|
||||
Wir werden eine Closure verwenden, um das DOM zu manipulieren.
|
||||
|
||||
Stellen Sie sich das DOM als einen Baum vor, der alle Möglichkeiten darstellt, wie ein Dokument einer Webseite manipuliert werden kann. Verschiedene APIs (Application Program Interfaces) wurden entwickelt, damit Programmierer mit ihrer bevorzugten Programmiersprache auf das DOM zugreifen und es bearbeiten, ändern, umorganisieren und verwalten können.
|
||||
|
||||

|
||||
|
||||
> Eine Darstellung des DOM und des HTML-Markups, das darauf verweist. Von [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
|
||||
|
||||
In dieser Lektion werden wir unser interaktives Terrarium-Projekt abschließen, indem wir das JavaScript erstellen, das es einem Benutzer ermöglicht, die Pflanzen auf der Seite zu manipulieren.
|
||||
|
||||
### Voraussetzung
|
||||
|
||||
Sie sollten das HTML und CSS für Ihr Terrarium bereits erstellt haben. Am Ende dieser Lektion werden Sie in der Lage sein, die Pflanzen durch Ziehen in und aus dem Terrarium zu bewegen.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Erstellen Sie in Ihrem Terrarium-Ordner eine neue Datei namens `script.js`. Importieren Sie diese Datei im `<head>`-Abschnitt:
|
||||
|
||||
```html
|
||||
<script src="./script.js" defer></script>
|
||||
```
|
||||
|
||||
> Hinweis: Verwenden Sie `defer`, wenn Sie eine externe JavaScript-Datei in die HTML-Datei importieren, damit das JavaScript erst ausgeführt wird, nachdem die HTML-Datei vollständig geladen wurde. Sie könnten auch das `async`-Attribut verwenden, das es dem Skript ermöglicht, während des Parsens der HTML-Datei ausgeführt zu werden. In unserem Fall ist es jedoch wichtig, dass die HTML-Elemente vollständig verfügbar sind, bevor wir das Drag-Skript ausführen.
|
||||
|
||||
---
|
||||
|
||||
## Die DOM-Elemente
|
||||
|
||||
Das Erste, was Sie tun müssen, ist, Referenzen zu den Elementen zu erstellen, die Sie im DOM manipulieren möchten. In unserem Fall sind dies die 14 Pflanzen, die derzeit in den Seitenleisten warten.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
```html
|
||||
dragElement(document.getElementById('plant1'));
|
||||
dragElement(document.getElementById('plant2'));
|
||||
dragElement(document.getElementById('plant3'));
|
||||
dragElement(document.getElementById('plant4'));
|
||||
dragElement(document.getElementById('plant5'));
|
||||
dragElement(document.getElementById('plant6'));
|
||||
dragElement(document.getElementById('plant7'));
|
||||
dragElement(document.getElementById('plant8'));
|
||||
dragElement(document.getElementById('plant9'));
|
||||
dragElement(document.getElementById('plant10'));
|
||||
dragElement(document.getElementById('plant11'));
|
||||
dragElement(document.getElementById('plant12'));
|
||||
dragElement(document.getElementById('plant13'));
|
||||
dragElement(document.getElementById('plant14'));
|
||||
```
|
||||
|
||||
Was passiert hier? Sie referenzieren das Dokument und durchsuchen dessen DOM, um ein Element mit einer bestimmten Id zu finden. Erinnern Sie sich an die erste Lektion über HTML, in der Sie jedem Pflanzenbild eine individuelle Id gegeben haben (`id="plant1"`)? Jetzt werden Sie diese Arbeit nutzen. Nachdem Sie jedes Element identifiziert haben, übergeben Sie dieses Element an eine Funktion namens `dragElement`, die Sie gleich erstellen werden. Somit ist das Element im HTML jetzt für das Ziehen aktiviert oder wird es bald sein.
|
||||
|
||||
✅ Warum referenzieren wir Elemente nach Id? Warum nicht nach ihrer CSS-Klasse? Sie könnten auf die vorherige Lektion über CSS zurückgreifen, um diese Frage zu beantworten.
|
||||
|
||||
---
|
||||
|
||||
## Die Closure
|
||||
|
||||
Jetzt sind Sie bereit, die `dragElement`-Closure zu erstellen, die eine äußere Funktion ist, die eine innere Funktion oder mehrere innere Funktionen umschließt (in unserem Fall werden es drei sein).
|
||||
|
||||
Closures sind nützlich, wenn eine oder mehrere Funktionen Zugriff auf den Scope einer äußeren Funktion benötigen. Hier ist ein Beispiel:
|
||||
|
||||
```javascript
|
||||
function displayCandy(){
|
||||
let candy = ['jellybeans'];
|
||||
function addCandy(candyType) {
|
||||
candy.push(candyType)
|
||||
}
|
||||
addCandy('gumdrops');
|
||||
}
|
||||
displayCandy();
|
||||
console.log(candy)
|
||||
```
|
||||
|
||||
In diesem Beispiel umgibt die Funktion `displayCandy` eine Funktion, die eine neue Süßigkeit in ein Array einfügt, das bereits in der Funktion existiert. Wenn Sie diesen Code ausführen würden, wäre das `candy`-Array undefiniert, da es eine lokale Variable ist (lokal zur Closure).
|
||||
|
||||
✅ Wie können Sie das `candy`-Array zugänglich machen? Versuchen Sie, es außerhalb der Closure zu verschieben. Auf diese Weise wird das Array global, anstatt nur im lokalen Scope der Closure verfügbar zu sein.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Erstellen Sie unter den Elementdeklarationen in `script.js` eine Funktion:
|
||||
|
||||
```javascript
|
||||
function dragElement(terrariumElement) {
|
||||
//set 4 positions for positioning on the screen
|
||||
let pos1 = 0,
|
||||
pos2 = 0,
|
||||
pos3 = 0,
|
||||
pos4 = 0;
|
||||
terrariumElement.onpointerdown = pointerDrag;
|
||||
}
|
||||
```
|
||||
|
||||
`dragElement` erhält sein `terrariumElement`-Objekt aus den Deklarationen am Anfang des Skripts. Dann setzen Sie einige lokale Positionen auf `0` für das Objekt, das in die Funktion übergeben wird. Dies sind die lokalen Variablen, die für jedes Element manipuliert werden, während Sie die Drag-and-Drop-Funktionalität innerhalb der Closure zu jedem Element hinzufügen. Das Terrarium wird von diesen gezogenen Elementen bevölkert, sodass die Anwendung den Überblick darüber behalten muss, wo sie platziert werden.
|
||||
|
||||
Darüber hinaus wird das `terrariumElement`, das an diese Funktion übergeben wird, einem `pointerdown`-Event zugewiesen, das Teil der [Web-APIs](https://developer.mozilla.org/docs/Web/API) ist, die für die DOM-Verwaltung entwickelt wurden. `onpointerdown` wird ausgelöst, wenn eine Taste gedrückt wird oder in unserem Fall ein ziehbares Element berührt wird. Dieser Event-Handler funktioniert sowohl auf [Web- als auch auf mobilen Browsern](https://caniuse.com/?search=onpointerdown), mit einigen Ausnahmen.
|
||||
|
||||
✅ Der [Event-Handler `onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) hat eine viel größere Unterstützung über verschiedene Browser hinweg; warum würden Sie ihn hier nicht verwenden? Denken Sie über die genaue Art der Bildschirminteraktion nach, die Sie hier erstellen möchten.
|
||||
|
||||
---
|
||||
|
||||
## Die Pointerdrag-Funktion
|
||||
|
||||
Das `terrariumElement` ist bereit, herumgezogen zu werden; wenn das `onpointerdown`-Event ausgelöst wird, wird die Funktion `pointerDrag` aufgerufen. Fügen Sie diese Funktion direkt unter dieser Zeile hinzu: `terrariumElement.onpointerdown = pointerDrag;`:
|
||||
|
||||
### Aufgabe
|
||||
|
||||
```javascript
|
||||
function pointerDrag(e) {
|
||||
e.preventDefault();
|
||||
console.log(e);
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
}
|
||||
```
|
||||
|
||||
Es passieren mehrere Dinge. Zunächst verhindern Sie die Standardereignisse, die normalerweise bei `pointerdown` auftreten, indem Sie `e.preventDefault();` verwenden. Auf diese Weise haben Sie mehr Kontrolle über das Verhalten der Benutzeroberfläche.
|
||||
|
||||
> Kehren Sie zu dieser Zeile zurück, wenn Sie die Skriptdatei vollständig erstellt haben, und versuchen Sie es ohne `e.preventDefault()` - was passiert?
|
||||
|
||||
Zweitens öffnen Sie `index.html` in einem Browserfenster und inspizieren die Benutzeroberfläche. Wenn Sie auf eine Pflanze klicken, können Sie sehen, wie das 'e'-Ereignis erfasst wird. Untersuchen Sie das Ereignis, um zu sehen, wie viele Informationen durch ein einziges `pointerdown`-Ereignis gesammelt werden!
|
||||
|
||||
Als Nächstes beachten Sie, wie die lokalen Variablen `pos3` und `pos4` auf `e.clientX` gesetzt werden. Sie können die `e`-Werte im Inspektionsfenster finden. Diese Werte erfassen die x- und y-Koordinaten der Pflanze in dem Moment, in dem Sie darauf klicken oder sie berühren. Sie benötigen eine feingranulare Kontrolle über das Verhalten der Pflanzen, während Sie sie anklicken und ziehen, daher behalten Sie ihre Koordinaten im Auge.
|
||||
|
||||
✅ Wird es klarer, warum diese gesamte App mit einer großen Closure erstellt wurde? Wenn nicht, wie würden Sie den Scope für jede der 14 ziehbaren Pflanzen aufrechterhalten?
|
||||
|
||||
Vervollständigen Sie die Anfangsfunktion, indem Sie zwei weitere Pointer-Ereignis-Manipulationen unter `pos4 = e.clientY` hinzufügen:
|
||||
|
||||
```html
|
||||
document.onpointermove = elementDrag;
|
||||
document.onpointerup = stopElementDrag;
|
||||
```
|
||||
|
||||
Jetzt geben Sie an, dass Sie möchten, dass die Pflanze zusammen mit dem Zeiger bewegt wird, während Sie sie ziehen, und dass die Ziehbewegung aufhört, wenn Sie die Pflanze abwählen. `onpointermove` und `onpointerup` sind alle Teil derselben API wie `onpointerdown`. Die Benutzeroberfläche wird jetzt Fehler werfen, da Sie die Funktionen `elementDrag` und `stopElementDrag` noch nicht definiert haben. Erstellen Sie diese als Nächstes.
|
||||
|
||||
## Die Funktionen elementDrag und stopElementDrag
|
||||
|
||||
Sie werden Ihre Closure vervollständigen, indem Sie zwei weitere interne Funktionen hinzufügen, die steuern, was passiert, wenn Sie eine Pflanze ziehen und das Ziehen beenden. Das gewünschte Verhalten ist, dass Sie jederzeit jede Pflanze ziehen und sie überall auf dem Bildschirm platzieren können. Diese Benutzeroberfläche ist ziemlich flexibel (es gibt beispielsweise keine Drop-Zone), sodass Sie Ihr Terrarium genau so gestalten können, wie Sie möchten, indem Sie Pflanzen hinzufügen, entfernen und neu positionieren.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Fügen Sie die Funktion `elementDrag` direkt nach der schließenden geschweiften Klammer von `pointerDrag` hinzu:
|
||||
|
||||
```javascript
|
||||
function elementDrag(e) {
|
||||
pos1 = pos3 - e.clientX;
|
||||
pos2 = pos4 - e.clientY;
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
console.log(pos1, pos2, pos3, pos4);
|
||||
terrariumElement.style.top = terrariumElement.offsetTop - pos2 + 'px';
|
||||
terrariumElement.style.left = terrariumElement.offsetLeft - pos1 + 'px';
|
||||
}
|
||||
```
|
||||
|
||||
In dieser Funktion bearbeiten Sie viele der Anfangspositionen 1-4, die Sie als lokale Variablen in der äußeren Funktion festgelegt haben. Was passiert hier?
|
||||
|
||||
Während Sie ziehen, weisen Sie `pos1` neu zu, indem Sie es gleich `pos3` setzen (das Sie zuvor als `e.clientX` festgelegt haben), minus dem aktuellen Wert von `e.clientX`. Eine ähnliche Operation führen Sie mit `pos2` durch. Dann setzen Sie `pos3` und `pos4` auf die neuen X- und Y-Koordinaten des Elements zurück. Sie können diese Änderungen in der Konsole beobachten, während Sie ziehen. Anschließend manipulieren Sie den CSS-Stil der Pflanze, um ihre neue Position basierend auf den neuen Positionen von `pos1` und `pos2` festzulegen, indem Sie die oberen und linken X- und Y-Koordinaten der Pflanze berechnen, basierend auf dem Vergleich ihres Offsets mit diesen neuen Positionen.
|
||||
|
||||
> `offsetTop` und `offsetLeft` sind CSS-Eigenschaften, die die Position eines Elements basierend auf der seines Elternteils festlegen; das Elternteil kann jedes Element sein, das nicht als `static` positioniert ist.
|
||||
|
||||
All diese Neuberechnungen der Position ermöglichen es Ihnen, das Verhalten des Terrariums und seiner Pflanzen fein abzustimmen.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Die letzte Aufgabe, um die Benutzeroberfläche zu vervollständigen, besteht darin, die Funktion `stopElementDrag` nach der schließenden geschweiften Klammer von `elementDrag` hinzuzufügen:
|
||||
|
||||
```javascript
|
||||
function stopElementDrag() {
|
||||
document.onpointerup = null;
|
||||
document.onpointermove = null;
|
||||
}
|
||||
```
|
||||
|
||||
Diese kleine Funktion setzt die Ereignisse `onpointerup` und `onpointermove` zurück, sodass Sie entweder den Fortschritt Ihrer Pflanze neu starten können, indem Sie sie erneut ziehen, oder beginnen können, eine neue Pflanze zu ziehen.
|
||||
|
||||
✅ Was passiert, wenn Sie diese Ereignisse nicht auf null setzen?
|
||||
|
||||
Jetzt haben Sie Ihr Projekt abgeschlossen!
|
||||
|
||||
🥇Herzlichen Glückwunsch! Sie haben Ihr wunderschönes Terrarium fertiggestellt. 
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Fügen Sie Ihrer Closure einen neuen Event-Handler hinzu, um den Pflanzen zusätzliche Funktionen zu geben; zum Beispiel, doppelklicken Sie auf eine Pflanze, um sie in den Vordergrund zu bringen. Werden Sie kreativ!
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/20)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Obwohl das Ziehen von Elementen über den Bildschirm trivial erscheint, gibt es viele Möglichkeiten, dies zu tun, und viele Fallstricke, abhängig von dem gewünschten Effekt. Tatsächlich gibt es eine gesamte [Drag-and-Drop-API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API), die Sie ausprobieren können. Wir haben sie in diesem Modul nicht verwendet, da der gewünschte Effekt etwas anders war, aber probieren Sie diese API in Ihrem eigenen Projekt aus und sehen Sie, was Sie erreichen können.
|
||||
|
||||
Weitere Informationen zu Pointer-Ereignissen finden Sie in den [W3C-Dokumenten](https://www.w3.org/TR/pointerevents1/) und in den [MDN-Web-Dokumenten](https://developer.mozilla.org/docs/Web/API/Pointer_events).
|
||||
|
||||
Überprüfen Sie immer die Browser-Kompatibilität mit [CanIUse.com](https://caniuse.com/).
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Arbeiten Sie ein wenig mehr mit dem DOM](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "22fb6c3cb570c47f1ac65048393941fa",
|
||||
"translation_date": "2025-08-24T12:07:00+00:00",
|
||||
"source_file": "3-terrarium/3-intro-to-DOM-and-closures/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Arbeite ein wenig mehr mit dem DOM
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Erforsche den DOM ein wenig mehr, indem du ein DOM-Element „adoptierst“. Besuche die [Liste der DOM-Schnittstellen](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) auf MDN und wähle eine aus. Finde ein Beispiel, wie sie auf einer Website im Web verwendet wird, und schreibe eine Erklärung, wie sie genutzt wird.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | --------------------------------------------- | ------------------------------------------------ | ----------------------- |
|
||||
| | Absatz mit Erklärung und Beispiel vorhanden | Absatz mit Erklärung, aber ohne Beispiel | Keine Erklärung vorhanden |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,43 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "7965cd2bc5dc92ad888dc4c6ab2ab70a",
|
||||
"translation_date": "2025-08-24T11:58:42+00:00",
|
||||
"source_file": "3-terrarium/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Mein Terrarium: Ein Projekt, um HTML, CSS und DOM-Manipulation mit JavaScript zu lernen 🌵🌱
|
||||
|
||||
Ein kleines Drag-and-Drop-Code-Meditationsprojekt. Mit ein wenig HTML, JS und CSS kannst du eine Weboberfläche erstellen, sie gestalten und sogar mehrere Interaktionen deiner Wahl hinzufügen.
|
||||
|
||||

|
||||
|
||||
# Lektionen
|
||||
|
||||
1. [Einführung in HTML](./1-intro-to-html/README.md)
|
||||
2. [Einführung in CSS](./2-intro-to-css/README.md)
|
||||
3. [Einführung in DOM und JS Closures](./3-intro-to-DOM-and-closures/README.md)
|
||||
|
||||
## Credits
|
||||
|
||||
Geschrieben mit ♥️ von [Jen Looper](https://www.twitter.com/jenlooper)
|
||||
|
||||
Das Terrarium, das mit CSS erstellt wurde, wurde von Jakub Mandras Glasgefäß [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY) inspiriert.
|
||||
|
||||
Die Illustrationen wurden von [Jen Looper](http://jenlooper.com) mit Hilfe von Procreate handgezeichnet.
|
||||
|
||||
## Veröffentliche dein Terrarium
|
||||
|
||||
Du kannst dein Terrarium im Web veröffentlichen, indem du Azure Static Web Apps nutzt.
|
||||
|
||||
1. Forke dieses Repository
|
||||
|
||||
2. Drücke diesen Button
|
||||
|
||||
[](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
|
||||
|
||||
3. Gehe den Assistenten durch, um deine App zu erstellen. Stelle sicher, dass du das App-Root entweder auf `/solution` oder das Root-Verzeichnis deines Codes setzt. Diese App hat keine API, also brauchst du dir darüber keine Gedanken zu machen. Ein GitHub-Ordner wird in deinem geforkten Repository erstellt, der den Build-Services von Azure Static Web Apps hilft, deine App zu erstellen und unter einer neuen URL zu veröffentlichen.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,37 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "6329fbe8bd936068debd78cca6f09c0a",
|
||||
"translation_date": "2025-08-24T12:11:12+00:00",
|
||||
"source_file": "3-terrarium/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Mein Terrarium: Ein Projekt, um HTML, CSS und DOM-Manipulation mit JavaScript zu lernen 🌵🌱
|
||||
|
||||
Ein kleines Drag-and-Drop-Code-Meditationsprojekt. Mit ein wenig HTML, JS und CSS kannst du eine Weboberfläche erstellen, sie gestalten und Interaktionen hinzufügen.
|
||||
|
||||

|
||||
|
||||
## Credits
|
||||
|
||||
Geschrieben mit ♥️ von [Jen Looper](https://www.twitter.com/jenlooper)
|
||||
|
||||
Das Terrarium, das mit CSS erstellt wurde, wurde von Jakub Mandras Glasgefäß [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY) inspiriert.
|
||||
|
||||
Die Illustrationen wurden von [Jen Looper](http://jenlooper.com) mit Procreate handgezeichnet.
|
||||
|
||||
## Dein Terrarium bereitstellen
|
||||
|
||||
Du kannst dein Terrarium mit Azure Static Web Apps im Web bereitstellen oder veröffentlichen.
|
||||
|
||||
1. Forke dieses Repository
|
||||
|
||||
2. Drücke diesen Button
|
||||
|
||||
[](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
|
||||
|
||||
3. Gehe den Assistenten durch, um deine App zu erstellen. Stelle sicher, dass du das App-Root entweder auf `/solution` oder das Root-Verzeichnis deines Codes setzt. Diese App hat keine API, also brauchst du dir darüber keine Gedanken zu machen. Ein .github-Ordner wird in deinem geforkten Repository erstellt, der dem Build-Service von Azure Static Web Apps hilft, deine App zu erstellen und unter einer neuen URL zu veröffentlichen.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,42 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "957547b822c40042e07d591c4fbfde4f",
|
||||
"translation_date": "2025-08-24T13:49:41+00:00",
|
||||
"source_file": "4-typing-game/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Ereignisgesteuerte Programmierung - Erstelle ein Tipp-Spiel
|
||||
|
||||
## Einführung
|
||||
|
||||
Tippen ist eine der am meisten unterschätzten Fähigkeiten eines Entwicklers. Die Fähigkeit, Gedanken schnell aus deinem Kopf in deinen Editor zu übertragen, ermöglicht es, dass die Kreativität frei fließen kann. Eine der besten Möglichkeiten zu lernen, ist ein Spiel zu spielen!
|
||||
|
||||
> Also, lass uns ein Tipp-Spiel erstellen!
|
||||
|
||||
Du wirst die JavaScript-, HTML- und CSS-Kenntnisse, die du bisher aufgebaut hast, nutzen, um ein Tipp-Spiel zu erstellen. Das Spiel wird dem Spieler ein zufälliges Zitat präsentieren (wir verwenden [Sherlock Holmes](https://en.wikipedia.org/wiki/Sherlock_Holmes)-Zitate) und messen, wie lange der Spieler braucht, um es genau abzutippen. Du wirst die JavaScript-, HTML- und CSS-Kenntnisse, die du bisher aufgebaut hast, nutzen, um ein Tipp-Spiel zu erstellen.
|
||||
|
||||

|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
Diese Lektion setzt voraus, dass du mit den folgenden Konzepten vertraut bist:
|
||||
|
||||
- Erstellen von Texteingaben und Button-Steuerelementen
|
||||
- CSS und das Festlegen von Stilen mithilfe von Klassen
|
||||
- Grundlagen von JavaScript
|
||||
- Erstellen eines Arrays
|
||||
- Erstellen einer Zufallszahl
|
||||
- Abrufen der aktuellen Zeit
|
||||
|
||||
## Lektion
|
||||
|
||||
[Erstellen eines Tipp-Spiels mithilfe ereignisgesteuerter Programmierung](./typing-game/README.md)
|
||||
|
||||
## Danksagung
|
||||
|
||||
Geschrieben mit ♥️ von [Christopher Harrison](http://www.twitter.com/geektrainer)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T13:50:27+00:00",
|
||||
"source_file": "4-typing-game/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,351 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "e982871b8388c59c22a41b73b5fca70f",
|
||||
"translation_date": "2025-08-24T13:51:57+00:00",
|
||||
"source_file": "4-typing-game/typing-game/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Ein Spiel mit Ereignissen erstellen
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/21)
|
||||
|
||||
## Ereignisgesteuerte Programmierung
|
||||
|
||||
Beim Erstellen einer browserbasierten Anwendung stellen wir eine grafische Benutzeroberfläche (GUI) bereit, die der Benutzer verwenden kann, um mit dem zu interagieren, was wir gebaut haben. Die häufigste Art, mit dem Browser zu interagieren, ist durch Klicken und Tippen auf verschiedene Elemente. Die Herausforderung, der wir als Entwickler gegenüberstehen, ist, dass wir nicht wissen, wann der Benutzer diese Aktionen ausführen wird!
|
||||
|
||||
[Ereignisgesteuerte Programmierung](https://de.wikipedia.org/wiki/Ereignisgesteuerte_Programmierung) ist der Name für die Art der Programmierung, die wir benötigen, um unsere GUI zu erstellen. Wenn wir diesen Begriff ein wenig aufschlüsseln, sehen wir, dass das Kernwort hier **Ereignis** ist. [Ereignis](https://www.merriam-webster.com/dictionary/event) wird laut Merriam-Webster definiert als "etwas, das passiert". Das beschreibt unsere Situation perfekt. Wir wissen, dass etwas passieren wird, für das wir Code ausführen möchten, aber wir wissen nicht, wann es stattfinden wird.
|
||||
|
||||
Die Art und Weise, wie wir einen Abschnitt von Code markieren, den wir ausführen möchten, besteht darin, eine Funktion zu erstellen. Wenn wir an [prozedurale Programmierung](https://de.wikipedia.org/wiki/Prozedurale_Programmierung) denken, werden Funktionen in einer bestimmten Reihenfolge aufgerufen. Dasselbe gilt auch für ereignisgesteuerte Programmierung. Der Unterschied liegt darin, **wie** die Funktionen aufgerufen werden.
|
||||
|
||||
Um Ereignisse (Button-Klicks, Eingaben usw.) zu behandeln, registrieren wir **Ereignis-Listener**. Ein Ereignis-Listener ist eine Funktion, die auf ein Ereignis wartet und daraufhin ausgeführt wird. Ereignis-Listener können die Benutzeroberfläche aktualisieren, Serveraufrufe durchführen oder alles andere erledigen, was als Reaktion auf die Aktion des Benutzers erforderlich ist. Wir fügen einen Ereignis-Listener hinzu, indem wir [addEventListener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) verwenden und eine Funktion bereitstellen, die ausgeführt werden soll.
|
||||
|
||||
> **NOTE:** Es ist erwähnenswert, dass es zahlreiche Möglichkeiten gibt, Ereignis-Listener zu erstellen. Sie können anonyme Funktionen verwenden oder benannte Funktionen erstellen. Sie können verschiedene Abkürzungen nutzen, wie das Setzen der `click`-Eigenschaft oder die Verwendung von `addEventListener`. In unserer Übung konzentrieren wir uns auf `addEventListener` und anonyme Funktionen, da dies wahrscheinlich die am häufigsten verwendete Technik von Webentwicklern ist. Es ist auch die flexibelste, da `addEventListener` für alle Ereignisse funktioniert und der Ereignisname als Parameter übergeben werden kann.
|
||||
|
||||
### Häufige Ereignisse
|
||||
|
||||
Es gibt [Dutzende von Ereignissen](https://developer.mozilla.org/docs/Web/Events), die Sie beim Erstellen einer Anwendung überwachen können. Grundsätzlich löst alles, was ein Benutzer auf einer Seite tut, ein Ereignis aus, was Ihnen viel Macht gibt, um sicherzustellen, dass der Benutzer die gewünschte Erfahrung erhält. Glücklicherweise benötigen Sie normalerweise nur eine kleine Auswahl an Ereignissen. Hier sind einige häufige (einschließlich der beiden, die wir beim Erstellen unseres Spiels verwenden werden):
|
||||
|
||||
- [click](https://developer.mozilla.org/docs/Web/API/Element/click_event): Der Benutzer hat auf etwas geklickt, typischerweise auf einen Button oder Hyperlink
|
||||
- [contextmenu](https://developer.mozilla.org/docs/Web/API/Element/contextmenu_event): Der Benutzer hat die rechte Maustaste geklickt
|
||||
- [select](https://developer.mozilla.org/docs/Web/API/Element/select_event): Der Benutzer hat Text markiert
|
||||
- [input](https://developer.mozilla.org/docs/Web/API/Element/input_event): Der Benutzer hat Text eingegeben
|
||||
|
||||
## Das Spiel erstellen
|
||||
|
||||
Wir werden ein Spiel erstellen, um zu erkunden, wie Ereignisse in JavaScript funktionieren. Unser Spiel wird die Tippfähigkeiten eines Spielers testen, eine der am meisten unterschätzten Fähigkeiten, die alle Entwickler haben sollten. Wir sollten alle unsere Tippfähigkeiten üben! Der allgemeine Ablauf des Spiels sieht folgendermaßen aus:
|
||||
|
||||
- Der Spieler klickt auf den Start-Button und erhält ein Zitat, das er tippen soll
|
||||
- Der Spieler tippt das Zitat so schnell wie möglich in ein Textfeld
|
||||
- Jedes Wort wird hervorgehoben, sobald es abgeschlossen ist
|
||||
- Wenn der Spieler einen Tippfehler macht, wird das Textfeld rot
|
||||
- Wenn der Spieler das Zitat abschließt, wird eine Erfolgsmeldung mit der verstrichenen Zeit angezeigt
|
||||
|
||||
Lassen Sie uns unser Spiel bauen und dabei etwas über Ereignisse lernen!
|
||||
|
||||
### Dateistruktur
|
||||
|
||||
Wir benötigen insgesamt drei Dateien: **index.html**, **script.js** und **style.css**. Lassen Sie uns diese einrichten, um uns die Arbeit zu erleichtern.
|
||||
|
||||
- Erstellen Sie einen neuen Ordner für Ihre Arbeit, indem Sie ein Konsolen- oder Terminalfenster öffnen und den folgenden Befehl ausführen:
|
||||
|
||||
```bash
|
||||
# Linux or macOS
|
||||
mkdir typing-game && cd typing-game
|
||||
|
||||
# Windows
|
||||
md typing-game && cd typing-game
|
||||
```
|
||||
|
||||
- Öffnen Sie Visual Studio Code
|
||||
|
||||
```bash
|
||||
code .
|
||||
```
|
||||
|
||||
- Fügen Sie dem Ordner in Visual Studio Code drei Dateien mit den folgenden Namen hinzu:
|
||||
- index.html
|
||||
- script.js
|
||||
- style.css
|
||||
|
||||
## Die Benutzeroberfläche erstellen
|
||||
|
||||
Wenn wir die Anforderungen untersuchen, wissen wir, dass wir eine Handvoll Elemente auf unserer HTML-Seite benötigen. Das ist ein bisschen wie ein Rezept, bei dem wir einige Zutaten brauchen:
|
||||
|
||||
- Einen Bereich, um das Zitat anzuzeigen, das der Benutzer tippen soll
|
||||
- Einen Bereich, um Nachrichten wie eine Erfolgsmeldung anzuzeigen
|
||||
- Ein Textfeld zum Tippen
|
||||
- Einen Start-Button
|
||||
|
||||
Jedes dieser Elemente benötigt IDs, damit wir mit ihnen in unserem JavaScript arbeiten können. Wir werden auch Verweise auf die CSS- und JavaScript-Dateien hinzufügen, die wir erstellen werden.
|
||||
|
||||
Erstellen Sie eine neue Datei namens **index.html**. Fügen Sie den folgenden HTML-Code hinzu:
|
||||
|
||||
```html
|
||||
<!-- inside index.html -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Typing game</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Typing game!</h1>
|
||||
<p>Practice your typing skills with a quote from Sherlock Holmes. Click **start** to begin!</p>
|
||||
<p id="quote"></p> <!-- This will display our quote -->
|
||||
<p id="message"></p> <!-- This will display any status messages -->
|
||||
<div>
|
||||
<input type="text" aria-label="current word" id="typed-value" /> <!-- The textbox for typing -->
|
||||
<button type="button" id="start">Start</button> <!-- To start the game -->
|
||||
</div>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Die Anwendung starten
|
||||
|
||||
Es ist immer am besten, iterativ zu entwickeln, um zu sehen, wie die Dinge aussehen. Lassen Sie uns unsere Anwendung starten. Es gibt eine wunderbare Erweiterung für Visual Studio Code namens [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), die Ihre Anwendung lokal hostet und den Browser jedes Mal aktualisiert, wenn Sie speichern.
|
||||
|
||||
- Installieren Sie [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), indem Sie dem Link folgen und auf **Installieren** klicken
|
||||
- Der Browser fordert Sie auf, Visual Studio Code zu öffnen, und Visual Studio Code fordert Sie auf, die Installation durchzuführen
|
||||
- Starten Sie Visual Studio Code neu, falls erforderlich
|
||||
- Sobald die Installation abgeschlossen ist, klicken Sie in Visual Studio Code auf Strg-Shift-P (oder Cmd-Shift-P), um die Befehls-Palette zu öffnen
|
||||
- Geben Sie **Live Server: Open with Live Server** ein
|
||||
- Live Server beginnt, Ihre Anwendung zu hosten
|
||||
- Öffnen Sie einen Browser und navigieren Sie zu **https://localhost:5500**
|
||||
- Sie sollten jetzt die Seite sehen, die Sie erstellt haben!
|
||||
|
||||
Lassen Sie uns etwas Funktionalität hinzufügen.
|
||||
|
||||
## CSS hinzufügen
|
||||
|
||||
Nachdem wir unser HTML erstellt haben, fügen wir das CSS für die grundlegende Gestaltung hinzu. Wir müssen das Wort hervorheben, das der Spieler tippen soll, und das Textfeld einfärben, wenn das, was er getippt hat, falsch ist. Wir werden dies mit zwei Klassen tun.
|
||||
|
||||
Erstellen Sie eine neue Datei namens **style.css** und fügen Sie den folgenden Syntax hinzu.
|
||||
|
||||
```css
|
||||
/* inside style.css */
|
||||
.highlight {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: lightcoral;
|
||||
border: red;
|
||||
}
|
||||
```
|
||||
|
||||
✅ Wenn es um CSS geht, können Sie Ihre Seite so gestalten, wie Sie möchten. Nehmen Sie sich etwas Zeit, um die Seite ansprechender zu gestalten:
|
||||
|
||||
- Wählen Sie eine andere Schriftart
|
||||
- Färben Sie die Überschriften ein
|
||||
- Ändern Sie die Größe der Elemente
|
||||
|
||||
## JavaScript
|
||||
|
||||
Nachdem wir unsere Benutzeroberfläche erstellt haben, konzentrieren wir uns nun auf das JavaScript, das die Logik bereitstellt. Wir werden dies in eine Handvoll Schritte unterteilen:
|
||||
|
||||
- [Die Konstanten erstellen](../../../../4-typing-game/typing-game)
|
||||
- [Ereignis-Listener für den Spielstart](../../../../4-typing-game/typing-game)
|
||||
- [Ereignis-Listener für das Tippen](../../../../4-typing-game/typing-game)
|
||||
|
||||
Erstellen Sie zunächst eine neue Datei namens **script.js**.
|
||||
|
||||
### Die Konstanten hinzufügen
|
||||
|
||||
Wir benötigen einige Elemente, um uns das Programmieren zu erleichtern. Wieder ähnlich wie ein Rezept, hier ist, was wir brauchen:
|
||||
|
||||
- Ein Array mit der Liste aller Zitate
|
||||
- Ein leeres Array, um alle Wörter des aktuellen Zitats zu speichern
|
||||
- Einen Speicherplatz für den Index des Wortes, das der Spieler gerade tippt
|
||||
- Die Zeit, zu der der Spieler auf Start geklickt hat
|
||||
|
||||
Wir möchten auch Verweise auf die UI-Elemente:
|
||||
|
||||
- Das Textfeld (**typed-value**)
|
||||
- Die Zitat-Anzeige (**quote**)
|
||||
- Die Nachricht (**message**)
|
||||
|
||||
```javascript
|
||||
// inside script.js
|
||||
// all of our quotes
|
||||
const quotes = [
|
||||
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
|
||||
'There is nothing more deceptive than an obvious fact.',
|
||||
'I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation.',
|
||||
'I never make exceptions. An exception disproves the rule.',
|
||||
'What one man can invent another can discover.',
|
||||
'Nothing clears up a case so much as stating it to another person.',
|
||||
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
|
||||
];
|
||||
// store the list of words and the index of the word the player is currently typing
|
||||
let words = [];
|
||||
let wordIndex = 0;
|
||||
// the starting time
|
||||
let startTime = Date.now();
|
||||
// page elements
|
||||
const quoteElement = document.getElementById('quote');
|
||||
const messageElement = document.getElementById('message');
|
||||
const typedValueElement = document.getElementById('typed-value');
|
||||
```
|
||||
|
||||
✅ Fügen Sie Ihrem Spiel weitere Zitate hinzu
|
||||
|
||||
> **NOTE:** Wir können die Elemente jederzeit im Code abrufen, indem wir `document.getElementById` verwenden. Da wir diese Elemente regelmäßig referenzieren werden, vermeiden wir Tippfehler mit Zeichenkettenliteralen, indem wir Konstanten verwenden. Frameworks wie [Vue.js](https://vuejs.org/) oder [React](https://reactjs.org/) können Ihnen helfen, Ihre zentrale Codeverwaltung besser zu organisieren.
|
||||
|
||||
Nehmen Sie sich eine Minute Zeit, um ein Video über die Verwendung von `const`, `let` und `var` anzusehen.
|
||||
|
||||
[](https://youtube.com/watch?v=JNIXfGiDWM8 "Arten von Variablen")
|
||||
|
||||
> 🎥 Klicken Sie auf das Bild oben, um ein Video über Variablen anzusehen.
|
||||
|
||||
### Start-Logik hinzufügen
|
||||
|
||||
Um das Spiel zu beginnen, klickt der Spieler auf Start. Natürlich wissen wir nicht, wann er auf Start klicken wird. Hier kommt ein [Ereignis-Listener](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) ins Spiel. Ein Ereignis-Listener ermöglicht es uns, auf etwas zu warten (ein Ereignis) und Code als Reaktion darauf auszuführen. In unserem Fall möchten wir Code ausführen, wenn der Benutzer auf Start klickt.
|
||||
|
||||
Wenn der Benutzer auf **Start** klickt, müssen wir ein Zitat auswählen, die Benutzeroberfläche einrichten und die Verfolgung des aktuellen Wortes und der Zeit einrichten. Unten finden Sie das JavaScript, das Sie hinzufügen müssen; wir besprechen es direkt nach dem Skriptblock.
|
||||
|
||||
```javascript
|
||||
// at the end of script.js
|
||||
document.getElementById('start').addEventListener('click', () => {
|
||||
// get a quote
|
||||
const quoteIndex = Math.floor(Math.random() * quotes.length);
|
||||
const quote = quotes[quoteIndex];
|
||||
// Put the quote into an array of words
|
||||
words = quote.split(' ');
|
||||
// reset the word index for tracking
|
||||
wordIndex = 0;
|
||||
|
||||
// UI updates
|
||||
// Create an array of span elements so we can set a class
|
||||
const spanWords = words.map(function(word) { return `<span>${word} </span>`});
|
||||
// Convert into string and set as innerHTML on quote display
|
||||
quoteElement.innerHTML = spanWords.join('');
|
||||
// Highlight the first word
|
||||
quoteElement.childNodes[0].className = 'highlight';
|
||||
// Clear any prior messages
|
||||
messageElement.innerText = '';
|
||||
|
||||
// Setup the textbox
|
||||
// Clear the textbox
|
||||
typedValueElement.value = '';
|
||||
// set focus
|
||||
typedValueElement.focus();
|
||||
// set the event handler
|
||||
|
||||
// Start the timer
|
||||
startTime = new Date().getTime();
|
||||
});
|
||||
```
|
||||
|
||||
Lassen Sie uns den Code aufschlüsseln!
|
||||
|
||||
- Einrichtung der Wortverfolgung
|
||||
- Mit [Math.floor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) und [Math.random](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random) können wir zufällig ein Zitat aus dem `quotes`-Array auswählen
|
||||
- Wir konvertieren das `quote` in ein Array von `words`, damit wir das Wort verfolgen können, das der Spieler gerade tippt
|
||||
- `wordIndex` wird auf 0 gesetzt, da der Spieler mit dem ersten Wort beginnt
|
||||
- Einrichtung der Benutzeroberfläche
|
||||
- Erstellen eines Arrays von `spanWords`, das jedes Wort in einem `span`-Element enthält
|
||||
- Dadurch können wir das Wort auf der Anzeige hervorheben
|
||||
- `join` des Arrays, um eine Zeichenkette zu erstellen, die wir verwenden können, um das `innerHTML` auf `quoteElement` zu aktualisieren
|
||||
- Dies zeigt dem Spieler das Zitat an
|
||||
- Setzen der `className` des ersten `span`-Elements auf `highlight`, um es gelb hervorzuheben
|
||||
- Bereinigen des `messageElement`, indem `innerText` auf `''` gesetzt wird
|
||||
- Einrichtung des Textfelds
|
||||
- Löschen des aktuellen `value` auf `typedValueElement`
|
||||
- Setzen des `focus` auf `typedValueElement`
|
||||
- Starten des Timers durch Aufrufen von `getTime`
|
||||
|
||||
### Tipp-Logik hinzufügen
|
||||
|
||||
Während der Spieler tippt, wird ein `input`-Ereignis ausgelöst. Dieser Ereignis-Listener überprüft, ob der Spieler das Wort korrekt tippt, und behandelt den aktuellen Status des Spiels. Kehren Sie zu **script.js** zurück und fügen Sie den folgenden Code am Ende hinzu. Wir werden ihn danach aufschlüsseln.
|
||||
|
||||
```javascript
|
||||
// at the end of script.js
|
||||
typedValueElement.addEventListener('input', () => {
|
||||
// Get the current word
|
||||
const currentWord = words[wordIndex];
|
||||
// get the current value
|
||||
const typedValue = typedValueElement.value;
|
||||
|
||||
if (typedValue === currentWord && wordIndex === words.length - 1) {
|
||||
// end of sentence
|
||||
// Display success
|
||||
const elapsedTime = new Date().getTime() - startTime;
|
||||
const message = `CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.`;
|
||||
messageElement.innerText = message;
|
||||
} else if (typedValue.endsWith(' ') && typedValue.trim() === currentWord) {
|
||||
// end of word
|
||||
// clear the typedValueElement for the new word
|
||||
typedValueElement.value = '';
|
||||
// move to the next word
|
||||
wordIndex++;
|
||||
// reset the class name for all elements in quote
|
||||
for (const wordElement of quoteElement.childNodes) {
|
||||
wordElement.className = '';
|
||||
}
|
||||
// highlight the new word
|
||||
quoteElement.childNodes[wordIndex].className = 'highlight';
|
||||
} else if (currentWord.startsWith(typedValue)) {
|
||||
// currently correct
|
||||
// highlight the next word
|
||||
typedValueElement.className = '';
|
||||
} else {
|
||||
// error state
|
||||
typedValueElement.className = 'error';
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Lassen Sie uns den Code aufschlüsseln! Wir beginnen damit, das aktuelle Wort und den Wert zu erfassen, den der Spieler bisher getippt hat. Dann haben wir eine Wasserfall-Logik, bei der wir überprüfen, ob das Zitat abgeschlossen ist, das Wort abgeschlossen ist, das Wort korrekt ist oder (schließlich), ob ein Fehler vorliegt.
|
||||
|
||||
- Das Zitat ist abgeschlossen, angezeigt durch `typedValue`, das gleich `currentWord` ist, und `wordIndex`, das gleich der Länge von `words` minus eins ist
|
||||
- Berechnen von `elapsedTime`, indem `startTime` von der aktuellen Zeit subtrahiert wird
|
||||
- Teilen von `elapsedTime` durch 1.000, um von Millisekunden in Sekunden umzuwandeln
|
||||
- Anzeigen einer Erfolgsmeldung
|
||||
- Das Wort ist abgeschlossen, angezeigt durch `typedValue`, das mit einem Leerzeichen endet (das Ende eines Wortes), und `typedValue`, das gleich `currentWord` ist
|
||||
- Setzen von `value` auf `typedElement` auf `''`, um das nächste Wort tippen zu können
|
||||
- Erhöhen von `wordIndex`, um zum nächsten Wort zu wechseln
|
||||
- Durchlaufen aller `childNodes` von `quoteElement`, um `className` auf `''` zu setzen, um die Standardanzeige wiederherzustellen
|
||||
- Setzen von `className` des aktuellen Wortes auf `highlight`, um es als nächstes zu tippendes Wort zu markieren
|
||||
- Das Wort wird derzeit korrekt getippt (aber nicht abgeschlossen), angezeigt durch `currentWord`, das mit `typedValue` beginnt
|
||||
- Sicherstellen, dass `typedValueElement` als Standard angezeigt wird, indem `className` gelöscht wird
|
||||
- Wenn wir bis hierher gekommen sind, liegt ein Fehler vor
|
||||
- Setzen von `className` auf `typedValueElement` auf `error`
|
||||
|
||||
## Testen Sie Ihre Anwendung
|
||||
|
||||
Sie haben es bis zum Ende geschafft! Der letzte Schritt besteht darin, sicherzustellen, dass unsere Anwendung funktioniert. Probieren Sie es aus! Machen Sie sich keine Sorgen, wenn es Fehler gibt; **alle Entwickler** haben Fehler. Untersuchen Sie die Nachrichten und debuggen Sie bei Bedarf.
|
||||
|
||||
Klicken Sie auf **Start** und beginnen Sie zu tippen! Es sollte ein wenig wie die Animation aussehen, die wir zuvor gesehen haben.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Fügen Sie weitere Funktionen hinzu:
|
||||
|
||||
- Deaktivieren Sie den `input`-Ereignis-Listener bei Abschluss und aktivieren Sie ihn erneut, wenn der Button geklickt wird
|
||||
- Deaktivieren Sie das Textfeld, wenn der Spieler das Zitat abschließt
|
||||
- Zeigen Sie ein modales Dialogfeld mit der Erfolgsmeldung an
|
||||
- Speichere hohe Punktzahlen mit [localStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage)
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/22)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Lies über [alle verfügbaren Ereignisse](https://developer.mozilla.org/docs/Web/Events), die Entwicklern über den Webbrowser zur Verfügung stehen, und überlege, in welchen Szenarien du jedes davon verwenden würdest.
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Erstelle ein neues Tastaturspiel](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,24 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "de5384c118e15e4d1d0eaa00fc01b112",
|
||||
"translation_date": "2025-08-24T13:55:20+00:00",
|
||||
"source_file": "4-typing-game/typing-game/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstelle ein neues Tastaturspiel
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Erstelle ein kleines Spiel, das Tastaturereignisse nutzt, um Aufgaben auszuführen. Es könnte eine andere Art von Tipp-Spiel sein oder ein Kunstspiel, das bei Tasteneingaben Pixel auf den Bildschirm malt. Sei kreativ!
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Ausreichend | Verbesserungswürdig |
|
||||
| --------- | ------------------------ | ------------------------ | -------------------- |
|
||||
| | Ein vollständiges Spiel wird präsentiert | Das Spiel ist sehr minimal | Das Spiel enthält Fehler |
|
||||
| | | | |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "e3c6f2a03c2336e60412612d870af547",
|
||||
"translation_date": "2025-08-24T13:15:43+00:00",
|
||||
"source_file": "5-browser-extension/1-about-browsers/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Gestalten Sie Ihre Erweiterung neu
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Der Code dieser Erweiterung enthält bereits Stile, aber Sie müssen diese nicht verwenden. Machen Sie die Erweiterung zu Ihrer eigenen, indem Sie die CSS-Datei bearbeiten und neu gestalten.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | -------------------------------------------- | --------------------- | ------------------- |
|
||||
| | Code wird mit funktionalen neuen Stilen eingereicht | Styling ist unvollständig | Stile sind fehlerhaft |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,238 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "e10f168beac4e7b05e30e0eb5c92bf11",
|
||||
"translation_date": "2025-08-24T13:09:10+00:00",
|
||||
"source_file": "5-browser-extension/2-forms-browsers-local-storage/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Browser-Erweiterungsprojekt Teil 2: Eine API aufrufen, Local Storage verwenden
|
||||
|
||||
## Quiz vor der Lektion
|
||||
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/25)
|
||||
|
||||
### Einführung
|
||||
|
||||
In dieser Lektion wirst du eine API aufrufen, indem du das Formular deiner Browser-Erweiterung übermittelst und die Ergebnisse in der Erweiterung anzeigst. Außerdem lernst du, wie du Daten im lokalen Speicher deines Browsers für zukünftige Verwendungen speichern kannst.
|
||||
|
||||
✅ Folge den nummerierten Abschnitten in den entsprechenden Dateien, um zu wissen, wo du deinen Code platzieren musst.
|
||||
|
||||
### Elemente für die Erweiterung vorbereiten:
|
||||
|
||||
Bis zu diesem Punkt hast du das HTML für das Formular und den `<div>`-Bereich für die Ergebnisse deiner Browser-Erweiterung erstellt. Ab jetzt wirst du in der Datei `/src/index.js` arbeiten und deine Erweiterung Schritt für Schritt aufbauen. Sieh dir die [vorherige Lektion](../1-about-browsers/README.md) an, um dein Projekt einzurichten und den Build-Prozess zu verstehen.
|
||||
|
||||
Arbeite in deiner `index.js`-Datei und beginne damit, einige `const`-Variablen zu erstellen, um die Werte der verschiedenen Felder zu speichern:
|
||||
|
||||
```JavaScript
|
||||
// form fields
|
||||
const form = document.querySelector('.form-data');
|
||||
const region = document.querySelector('.region-name');
|
||||
const apiKey = document.querySelector('.api-key');
|
||||
|
||||
// results
|
||||
const errors = document.querySelector('.errors');
|
||||
const loading = document.querySelector('.loading');
|
||||
const results = document.querySelector('.result-container');
|
||||
const usage = document.querySelector('.carbon-usage');
|
||||
const fossilfuel = document.querySelector('.fossil-fuel');
|
||||
const myregion = document.querySelector('.my-region');
|
||||
const clearBtn = document.querySelector('.clear-btn');
|
||||
```
|
||||
|
||||
Alle diese Felder werden über ihre CSS-Klasse referenziert, wie du sie im HTML in der vorherigen Lektion eingerichtet hast.
|
||||
|
||||
### Event Listener hinzufügen
|
||||
|
||||
Als Nächstes füge Event Listener für das Formular und die Schaltfläche zum Zurücksetzen hinzu, sodass etwas passiert, wenn ein Benutzer das Formular übermittelt oder die Schaltfläche klickt. Füge außerdem den Aufruf zur Initialisierung der App am Ende der Datei hinzu:
|
||||
|
||||
```JavaScript
|
||||
form.addEventListener('submit', (e) => handleSubmit(e));
|
||||
clearBtn.addEventListener('click', (e) => reset(e));
|
||||
init();
|
||||
```
|
||||
|
||||
✅ Beachte die Kurzschreibweise, die verwendet wird, um auf ein Submit- oder Click-Event zu hören, und wie das Event an die Funktionen `handleSubmit` oder `reset` übergeben wird. Kannst du die äquivalente Langform dieser Kurzschreibweise schreiben? Welche bevorzugst du?
|
||||
|
||||
### Die Funktionen `init()` und `reset()` erstellen:
|
||||
|
||||
Jetzt wirst du die Funktion erstellen, die die Erweiterung initialisiert, genannt `init()`:
|
||||
|
||||
```JavaScript
|
||||
function init() {
|
||||
//if anything is in localStorage, pick it up
|
||||
const storedApiKey = localStorage.getItem('apiKey');
|
||||
const storedRegion = localStorage.getItem('regionName');
|
||||
|
||||
//set icon to be generic green
|
||||
//todo
|
||||
|
||||
if (storedApiKey === null || storedRegion === null) {
|
||||
//if we don't have the keys, show the form
|
||||
form.style.display = 'block';
|
||||
results.style.display = 'none';
|
||||
loading.style.display = 'none';
|
||||
clearBtn.style.display = 'none';
|
||||
errors.textContent = '';
|
||||
} else {
|
||||
//if we have saved keys/regions in localStorage, show results when they load
|
||||
displayCarbonUsage(storedApiKey, storedRegion);
|
||||
results.style.display = 'none';
|
||||
form.style.display = 'none';
|
||||
clearBtn.style.display = 'block';
|
||||
}
|
||||
};
|
||||
|
||||
function reset(e) {
|
||||
e.preventDefault();
|
||||
//clear local storage for region only
|
||||
localStorage.removeItem('regionName');
|
||||
init();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
In dieser Funktion gibt es interessante Logik. Kannst du nachvollziehen, was passiert?
|
||||
|
||||
- Zwei `const`-Variablen werden eingerichtet, um zu prüfen, ob der Benutzer einen API-Schlüssel und einen Regionscode im lokalen Speicher gespeichert hat.
|
||||
- Wenn einer dieser Werte null ist, wird das Formular angezeigt, indem sein Stil auf 'block' gesetzt wird.
|
||||
- Die Bereiche für Ergebnisse, Ladeanzeige und die Schaltfläche zum Zurücksetzen werden ausgeblendet, und etwaiger Fehlertext wird auf einen leeren String gesetzt.
|
||||
- Wenn ein Schlüssel und eine Region vorhanden sind, wird eine Routine gestartet, um:
|
||||
- die API aufzurufen, um Daten zur Kohlenstoffnutzung abzurufen,
|
||||
- den Ergebnisbereich auszublenden,
|
||||
- das Formular auszublenden,
|
||||
- die Schaltfläche zum Zurücksetzen anzuzeigen.
|
||||
|
||||
Bevor du weitermachst, ist es nützlich, ein sehr wichtiges Konzept in Browsern zu lernen: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage). LocalStorage ist eine nützliche Möglichkeit, Zeichenketten im Browser als `key-value`-Paar zu speichern. Diese Art von Webspeicher kann durch JavaScript manipuliert werden, um Daten im Browser zu verwalten. LocalStorage läuft nicht ab, während SessionStorage, eine andere Art von Webspeicher, gelöscht wird, wenn der Browser geschlossen wird. Die verschiedenen Speicherarten haben Vor- und Nachteile.
|
||||
|
||||
> Hinweis: Deine Browser-Erweiterung hat ihren eigenen lokalen Speicher; das Hauptbrowserfenster ist eine separate Instanz und verhält sich unabhängig.
|
||||
|
||||
Du kannst deinen API-Schlüssel beispielsweise als Zeichenkette speichern und ihn in Edge sehen, indem du eine Webseite "inspizierst" (du kannst mit der rechten Maustaste auf einen Browser klicken, um zu inspizieren) und zum Tab "Applications" gehst, um den Speicher zu sehen.
|
||||
|
||||

|
||||
|
||||
✅ Überlege dir Situationen, in denen du keine Daten im LocalStorage speichern möchtest. Im Allgemeinen ist es eine schlechte Idee, API-Schlüssel im LocalStorage zu speichern! Kannst du nachvollziehen, warum? In unserem Fall, da unsere App rein zu Lernzwecken dient und nicht in einem App-Store veröffentlicht wird, verwenden wir diese Methode.
|
||||
|
||||
Beachte, dass du die Web-API verwenden kannst, um LocalStorage zu manipulieren, entweder mit `getItem()`, `setItem()` oder `removeItem()`. Es wird von den meisten Browsern unterstützt.
|
||||
|
||||
Bevor du die Funktion `displayCarbonUsage()` erstellst, die in `init()` aufgerufen wird, lass uns die Funktionalität für die anfängliche Formularübermittlung erstellen.
|
||||
|
||||
### Formularübermittlung verarbeiten
|
||||
|
||||
Erstelle eine Funktion namens `handleSubmit`, die ein Event-Argument `(e)` akzeptiert. Stoppe die Weiterleitung des Events (in diesem Fall möchten wir verhindern, dass der Browser aktualisiert wird) und rufe eine neue Funktion `setUpUser` auf, indem du die Argumente `apiKey.value` und `region.value` übergibst. Auf diese Weise verwendest du die beiden Werte, die über das anfängliche Formular eingegeben werden, wenn die entsprechenden Felder ausgefüllt sind.
|
||||
|
||||
```JavaScript
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
setUpUser(apiKey.value, region.value);
|
||||
}
|
||||
```
|
||||
|
||||
✅ Erinnere dich: Das HTML, das du in der letzten Lektion eingerichtet hast, hat zwei Eingabefelder, deren `values` über die `const`-Variablen, die du oben in der Datei eingerichtet hast, erfasst werden. Beide Felder sind `required`, sodass der Browser Benutzer daran hindert, null Werte einzugeben.
|
||||
|
||||
### Benutzer einrichten
|
||||
|
||||
Weiter geht es mit der Funktion `setUpUser`. Hier werden die Werte für `apiKey` und `regionName` im lokalen Speicher gesetzt. Füge eine neue Funktion hinzu:
|
||||
|
||||
```JavaScript
|
||||
function setUpUser(apiKey, regionName) {
|
||||
localStorage.setItem('apiKey', apiKey);
|
||||
localStorage.setItem('regionName', regionName);
|
||||
loading.style.display = 'block';
|
||||
errors.textContent = '';
|
||||
clearBtn.style.display = 'block';
|
||||
//make initial call
|
||||
displayCarbonUsage(apiKey, regionName);
|
||||
}
|
||||
```
|
||||
|
||||
Diese Funktion zeigt eine Ladeanzeige, während die API aufgerufen wird. An diesem Punkt hast du die wichtigste Funktion dieser Browser-Erweiterung erreicht!
|
||||
|
||||
### Kohlenstoffnutzung anzeigen
|
||||
|
||||
Endlich ist es Zeit, die API abzufragen!
|
||||
|
||||
Bevor wir weitermachen, sollten wir über APIs sprechen. APIs, oder [Application Programming Interfaces](https://www.webopedia.com/TERM/A/API.html), sind ein kritisches Element im Werkzeugkasten eines Webentwicklers. Sie bieten standardisierte Möglichkeiten, wie Programme miteinander interagieren und Schnittstellen bereitstellen können. Wenn du beispielsweise eine Website erstellst, die eine Datenbank abfragen muss, könnte jemand eine API dafür erstellt haben. Während es viele Arten von APIs gibt, ist eine der beliebtesten eine [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/).
|
||||
|
||||
✅ Der Begriff 'REST' steht für 'Representational State Transfer' und verwendet unterschiedlich konfigurierte URLs, um Daten abzurufen. Recherchiere ein wenig über die verschiedenen Arten von APIs, die Entwicklern zur Verfügung stehen. Welches Format spricht dich an?
|
||||
|
||||
Es gibt wichtige Dinge, die du über diese Funktion beachten solltest. Zunächst fällt das [`async`-Schlüsselwort](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) auf. Funktionen so zu schreiben, dass sie asynchron ausgeführt werden, bedeutet, dass sie auf eine Aktion, wie das Abrufen von Daten, warten, bevor sie fortfahren.
|
||||
|
||||
Hier ist ein kurzes Video über `async`:
|
||||
|
||||
[](https://youtube.com/watch?v=YwmlRkrxvkk "Async und Await für die Verwaltung von Promises")
|
||||
|
||||
> 🎥 Klicke auf das Bild oben für ein Video über async/await.
|
||||
|
||||
Erstelle eine neue Funktion, um die C02Signal API abzufragen:
|
||||
|
||||
```JavaScript
|
||||
import axios from '../node_modules/axios';
|
||||
|
||||
async function displayCarbonUsage(apiKey, region) {
|
||||
try {
|
||||
await axios
|
||||
.get('https://api.co2signal.com/v1/latest', {
|
||||
params: {
|
||||
countryCode: region,
|
||||
},
|
||||
headers: {
|
||||
'auth-token': apiKey,
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
let CO2 = Math.floor(response.data.data.carbonIntensity);
|
||||
|
||||
//calculateColor(CO2);
|
||||
|
||||
loading.style.display = 'none';
|
||||
form.style.display = 'none';
|
||||
myregion.textContent = region;
|
||||
usage.textContent =
|
||||
Math.round(response.data.data.carbonIntensity) + ' grams (grams C02 emitted per kilowatt hour)';
|
||||
fossilfuel.textContent =
|
||||
response.data.data.fossilFuelPercentage.toFixed(2) +
|
||||
'% (percentage of fossil fuels used to generate electricity)';
|
||||
results.style.display = 'block';
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
loading.style.display = 'none';
|
||||
results.style.display = 'none';
|
||||
errors.textContent = 'Sorry, we have no data for the region you have requested.';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Das ist eine große Funktion. Was passiert hier?
|
||||
|
||||
- Nach Best Practices verwendest du das `async`-Schlüsselwort, um diese Funktion asynchron zu gestalten. Die Funktion enthält einen `try/catch`-Block, da sie ein Promise zurückgibt, wenn die API Daten liefert. Da du keine Kontrolle über die Geschwindigkeit hast, mit der die API antwortet (oder ob sie überhaupt antwortet!), musst du diese Unsicherheit durch asynchrone Aufrufe handhaben.
|
||||
- Du fragst die co2signal API ab, um die Daten deiner Region zu erhalten, und verwendest deinen API-Schlüssel. Um diesen Schlüssel zu verwenden, musst du eine Art Authentifizierung in deinen Header-Parametern einfügen.
|
||||
- Sobald die API antwortet, weist du verschiedene Elemente ihrer Antwortdaten den Bereichen deines Bildschirms zu, die du eingerichtet hast, um diese Daten anzuzeigen.
|
||||
- Wenn ein Fehler auftritt oder keine Ergebnisse vorliegen, zeigst du eine Fehlermeldung an.
|
||||
|
||||
✅ Asynchrone Programmiermuster sind ein weiteres sehr nützliches Werkzeug in deinem Werkzeugkasten. Lies [über die verschiedenen Möglichkeiten](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function), wie du diese Art von Code konfigurieren kannst.
|
||||
|
||||
Herzlichen Glückwunsch! Wenn du deine Erweiterung baust (`npm run build`) und sie im Erweiterungsbereich aktualisierst, hast du eine funktionierende Erweiterung! Das einzige, was noch nicht funktioniert, ist das Symbol, und das wirst du in der nächsten Lektion beheben.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Wir haben in diesen Lektionen mehrere Arten von APIs besprochen. Wähle eine Web-API aus und recherchiere ausführlich, was sie bietet. Schau dir beispielsweise APIs an, die in Browsern verfügbar sind, wie die [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API). Was macht deiner Meinung nach eine großartige API aus?
|
||||
|
||||
## Quiz nach der Lektion
|
||||
|
||||
[Quiz nach der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/26)
|
||||
|
||||
## Rückblick & Selbststudium
|
||||
|
||||
In dieser Lektion hast du etwas über LocalStorage und APIs gelernt, beides sehr nützliche Werkzeuge für professionelle Webentwickler. Kannst du darüber nachdenken, wie diese beiden Dinge zusammenarbeiten? Überlege, wie du eine Website gestalten würdest, die Elemente speichert, die von einer API verwendet werden.
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Adoptiere eine API](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,174 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "f198c6b817b4b2a99749f4662e7cae98",
|
||||
"translation_date": "2025-08-24T13:17:00+00:00",
|
||||
"source_file": "5-browser-extension/3-background-tasks-and-performance/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Browser-Erweiterungsprojekt Teil 3: Lernen über Hintergrundaufgaben und Leistung
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/27)
|
||||
|
||||
### Einführung
|
||||
|
||||
In den letzten beiden Lektionen dieses Moduls hast du gelernt, wie man ein Formular und einen Anzeigebereich für Daten erstellt, die von einer API abgerufen werden. Dies ist eine sehr gängige Methode, um eine Webpräsenz zu erstellen. Du hast sogar gelernt, wie man Daten asynchron abruft. Deine Browser-Erweiterung ist fast fertig.
|
||||
|
||||
Es bleibt, einige Hintergrundaufgaben zu verwalten, einschließlich der Aktualisierung der Farbe des Erweiterungssymbols. Dies ist ein guter Zeitpunkt, um darüber zu sprechen, wie der Browser solche Aufgaben verwaltet. Lass uns über diese Browser-Aufgaben im Kontext der Leistung deiner Webressourcen nachdenken, während du sie erstellst.
|
||||
|
||||
## Grundlagen der Web-Leistung
|
||||
|
||||
> "Website-Leistung dreht sich um zwei Dinge: wie schnell die Seite lädt und wie schnell der Code darauf ausgeführt wird." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
|
||||
|
||||
Das Thema, wie man Websites auf allen Arten von Geräten, für alle Arten von Benutzern und in allen möglichen Situationen blitzschnell macht, ist erwartungsgemäß umfangreich. Hier sind einige Punkte, die du beachten solltest, wenn du entweder ein Standard-Webprojekt oder eine Browser-Erweiterung erstellst.
|
||||
|
||||
Das Erste, was du tun musst, um sicherzustellen, dass deine Website effizient läuft, ist, Daten über ihre Leistung zu sammeln. Der erste Ort, um dies zu tun, sind die Entwicklertools deines Webbrowsers. In Edge kannst du die Schaltfläche "Einstellungen und mehr" (das Drei-Punkte-Symbol oben rechts im Browser) auswählen, dann zu Weitere Tools > Entwicklertools navigieren und den Tab Leistung öffnen. Du kannst auch die Tastenkombination `Strg` + `Umschalt` + `I` unter Windows oder `Option` + `Befehl` + `I` auf dem Mac verwenden, um die Entwicklertools zu öffnen.
|
||||
|
||||
Der Tab Leistung enthält ein Profiling-Tool. Öffne eine Website (probiere zum Beispiel [https://www.microsoft.com](https://www.microsoft.com/?WT.mc_id=academic-77807-sagibbon)) und klicke auf die Schaltfläche "Aufzeichnen", dann aktualisiere die Website. Beende die Aufzeichnung jederzeit, und du kannst die Routinen sehen, die generiert werden, um die Website zu 'skripten', 'rendern' und 'malen':
|
||||
|
||||

|
||||
|
||||
✅ Besuche die [Microsoft-Dokumentation](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) zum Leistungspanel in Edge.
|
||||
|
||||
> Tipp: Um eine genaue Messung der Startzeit deiner Website zu erhalten, leere den Cache deines Browsers.
|
||||
|
||||
Wähle Elemente der Profil-Zeitleiste aus, um Ereignisse zu vergrößern, die während des Ladens deiner Seite auftreten.
|
||||
|
||||
Erhalte eine Momentaufnahme der Leistung deiner Seite, indem du einen Teil der Profil-Zeitleiste auswählst und das Zusammenfassungsfenster ansiehst:
|
||||
|
||||

|
||||
|
||||
Überprüfe das Ereignisprotokoll, um zu sehen, ob ein Ereignis länger als 15 ms gedauert hat:
|
||||
|
||||

|
||||
|
||||
✅ Lerne deinen Profiler kennen! Öffne die Entwicklertools auf dieser Website und sieh nach, ob es Engpässe gibt. Was ist die am langsamsten ladende Ressource? Die schnellste?
|
||||
|
||||
## Profiling-Checks
|
||||
|
||||
Im Allgemeinen gibt es einige "Problemzonen", die jeder Webentwickler im Auge behalten sollte, wenn er eine Website erstellt, um unangenehme Überraschungen beim Einsatz in der Produktion zu vermeiden.
|
||||
|
||||
**Asset-Größen**: Das Web ist in den letzten Jahren "schwerer" und damit langsamer geworden. Ein Teil dieses Gewichts hat mit der Verwendung von Bildern zu tun.
|
||||
|
||||
✅ Sieh dir das [Internet-Archiv](https://httparchive.org/reports/page-weight) für eine historische Ansicht des Seitengewichts und mehr an.
|
||||
|
||||
Eine gute Praxis ist sicherzustellen, dass deine Bilder optimiert sind und in der richtigen Größe und Auflösung für deine Benutzer geliefert werden.
|
||||
|
||||
**DOM-Traversierungen**: Der Browser muss sein Document Object Model basierend auf dem von dir geschriebenen Code erstellen, daher ist es im Interesse einer guten Seitenleistung, deine Tags minimal zu halten und nur das zu verwenden und zu stylen, was die Seite benötigt. Zu diesem Punkt könnte überschüssiges CSS, das mit einer Seite verbunden ist, optimiert werden; Stile, die nur auf einer Seite verwendet werden müssen, müssen beispielsweise nicht im Hauptstilblatt enthalten sein.
|
||||
|
||||
**JavaScript**: Jeder JavaScript-Entwickler sollte auf 'render-blockierende' Skripte achten, die geladen werden müssen, bevor der Rest des DOM durchlaufen und im Browser dargestellt werden kann. Erwäge die Verwendung von `defer` mit deinen Inline-Skripten (wie im Terrarium-Modul gemacht).
|
||||
|
||||
✅ Probiere einige Websites auf einer [Website-Geschwindigkeitstest-Seite](https://www.webpagetest.org/) aus, um mehr über die üblichen Checks zu erfahren, die durchgeführt werden, um die Leistung einer Website zu bestimmen.
|
||||
|
||||
Jetzt, da du eine Vorstellung davon hast, wie der Browser die von dir gesendeten Ressourcen rendert, lass uns die letzten Dinge ansehen, die du tun musst, um deine Erweiterung abzuschließen:
|
||||
|
||||
### Eine Funktion zur Farbberechnung erstellen
|
||||
|
||||
Arbeite in `/src/index.js` und füge eine Funktion namens `calculateColor()` nach der Reihe von `const`-Variablen hinzu, die du gesetzt hast, um Zugriff auf das DOM zu erhalten:
|
||||
|
||||
```JavaScript
|
||||
function calculateColor(value) {
|
||||
let co2Scale = [0, 150, 600, 750, 800];
|
||||
let colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02'];
|
||||
|
||||
let closestNum = co2Scale.sort((a, b) => {
|
||||
return Math.abs(a - value) - Math.abs(b - value);
|
||||
})[0];
|
||||
console.log(value + ' is closest to ' + closestNum);
|
||||
let num = (element) => element > closestNum;
|
||||
let scaleIndex = co2Scale.findIndex(num);
|
||||
|
||||
let closestColor = colors[scaleIndex];
|
||||
console.log(scaleIndex, closestColor);
|
||||
|
||||
chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: closestColor } });
|
||||
}
|
||||
```
|
||||
|
||||
Was passiert hier? Du übergibst einen Wert (die Kohlenstoffintensität) aus dem API-Aufruf, den du in der letzten Lektion abgeschlossen hast, und berechnest dann, wie nah sein Wert am Index im Farben-Array liegt. Dann sendest du diesen nächstgelegenen Farbwert an die Chrome-Laufzeit.
|
||||
|
||||
Die chrome.runtime hat [eine API](https://developer.chrome.com/extensions/runtime), die alle Arten von Hintergrundaufgaben verwaltet, und deine Erweiterung nutzt diese:
|
||||
|
||||
> "Verwende die chrome.runtime API, um die Hintergrundseite abzurufen, Details über das Manifest zurückzugeben und auf Ereignisse im Lebenszyklus der App oder Erweiterung zu hören und darauf zu reagieren. Du kannst diese API auch verwenden, um den relativen Pfad von URLs in vollständig qualifizierte URLs umzuwandeln."
|
||||
|
||||
✅ Wenn du diese Browser-Erweiterung für Edge entwickelst, könnte es dich überraschen, dass du eine Chrome-API verwendest. Die neueren Edge-Browser-Versionen laufen auf der Chromium-Browser-Engine, sodass du diese Tools nutzen kannst.
|
||||
|
||||
> Hinweis: Wenn du eine Browser-Erweiterung profilieren möchtest, starte die Entwicklertools innerhalb der Erweiterung selbst, da sie eine eigene separate Browser-Instanz ist.
|
||||
|
||||
### Eine Standard-Symbolfarbe festlegen
|
||||
|
||||
Setze nun in der `init()`-Funktion das Symbol zunächst auf ein generisches Grün, indem du erneut die `updateIcon`-Aktion von Chrome aufrufst:
|
||||
|
||||
```JavaScript
|
||||
chrome.runtime.sendMessage({
|
||||
action: 'updateIcon',
|
||||
value: {
|
||||
color: 'green',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Die Funktion aufrufen und den Aufruf ausführen
|
||||
|
||||
Rufe als Nächstes die Funktion, die du gerade erstellt hast, auf, indem du sie dem Promise hinzufügst, das von der C02Signal-API zurückgegeben wird:
|
||||
|
||||
```JavaScript
|
||||
//let CO2...
|
||||
calculateColor(CO2);
|
||||
```
|
||||
|
||||
Und schließlich füge in `/dist/background.js` den Listener für diese Hintergrundaktionsaufrufe hinzu:
|
||||
|
||||
```JavaScript
|
||||
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
|
||||
if (msg.action === 'updateIcon') {
|
||||
chrome.browserAction.setIcon({ imageData: drawIcon(msg.value) });
|
||||
}
|
||||
});
|
||||
//borrowed from energy lollipop extension, nice feature!
|
||||
function drawIcon(value) {
|
||||
let canvas = document.createElement('canvas');
|
||||
let context = canvas.getContext('2d');
|
||||
|
||||
context.beginPath();
|
||||
context.fillStyle = value.color;
|
||||
context.arc(100, 100, 50, 0, 2 * Math.PI);
|
||||
context.fill();
|
||||
|
||||
return context.getImageData(50, 50, 100, 100);
|
||||
}
|
||||
```
|
||||
|
||||
In diesem Code fügst du einen Listener für alle Nachrichten hinzu, die an den Backend-Aufgabenmanager gesendet werden. Wenn er 'updateIcon' genannt wird, wird der nächste Code ausgeführt, um ein Symbol der richtigen Farbe mit der Canvas-API zu zeichnen.
|
||||
|
||||
✅ Du wirst mehr über die Canvas-API in den [Space Game-Lektionen](../../6-space-game/2-drawing-to-canvas/README.md) lernen.
|
||||
|
||||
Baue nun deine Erweiterung neu (`npm run build`), aktualisiere und starte deine Erweiterung und beobachte, wie sich die Farbe ändert. Ist es ein guter Zeitpunkt, Besorgungen zu machen oder das Geschirr zu spülen? Jetzt weißt du es!
|
||||
|
||||
Herzlichen Glückwunsch, du hast eine nützliche Browser-Erweiterung erstellt und mehr darüber gelernt, wie der Browser funktioniert und wie man seine Leistung profiliert.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Untersuche einige Open-Source-Websites, die es schon lange gibt, und versuche basierend auf ihrer GitHub-Historie herauszufinden, wie sie im Laufe der Jahre für die Leistung optimiert wurden, falls überhaupt. Was ist der häufigste Schmerzpunkt?
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/28)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Erwäge, dich für einen [Leistungs-Newsletter](https://perf.email/) anzumelden.
|
||||
|
||||
Untersuche einige der Möglichkeiten, wie Browser die Web-Leistung messen, indem du die Leistungstabs in ihren Webtools durchsiehst. Findest du größere Unterschiede?
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Analysiere eine Website auf Leistung](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "fc09b0fb314a5ab0507ba99216e6a843",
|
||||
"translation_date": "2025-08-24T13:18:57+00:00",
|
||||
"source_file": "5-browser-extension/3-background-tasks-and-performance/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Analysiere eine Website auf Leistung
|
||||
|
||||
Erstelle einen detaillierten Bericht über eine Website, der Bereiche aufzeigt, in denen die Leistung problematisch ist. Analysiere, warum die Website langsam ist, und was du tun könntest, um sie zu beschleunigen. Verlasse dich nicht nur auf die Browser-Tools, sondern recherchiere auch nach anderen Tools, die deinen Bericht unterstützen können.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | -------------------------------------------------------------------------------------------------------- | --------------------------- | ----------------------------- |
|
||||
| | Ein Bericht wird präsentiert, der nicht nur auf Browser-Tools, sondern, wenn verfügbar, auch auf Drittanbieter-Tools basiert | Ein grundlegender Bericht wird präsentiert | Ein minimaler Bericht wird präsentiert |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "b121a279a6ab39878491f3e572673515",
|
||||
"translation_date": "2025-08-24T13:07:42+00:00",
|
||||
"source_file": "5-browser-extension/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstellen einer Browser-Erweiterung
|
||||
|
||||
Das Erstellen von Browser-Erweiterungen ist eine unterhaltsame und interessante Möglichkeit, über die Leistung Ihrer Apps nachzudenken, während Sie eine andere Art von Web-Asset entwickeln. Dieses Modul enthält Lektionen darüber, wie Browser funktionieren und wie man eine Browser-Erweiterung bereitstellt, wie man ein Formular erstellt, eine API aufruft und lokalen Speicher verwendet, sowie wie man die Leistung Ihrer Website bewertet und verbessert.
|
||||
|
||||
Sie werden eine Browser-Erweiterung erstellen, die mit Edge, Chrome und Firefox funktioniert. Diese Erweiterung, die wie eine Mini-Website ist, die auf eine sehr spezifische Aufgabe zugeschnitten ist, überprüft die [C02 Signal API](https://www.co2signal.com) für den Stromverbrauch und die Kohlenstoffintensität einer bestimmten Region und liefert eine Bewertung des Kohlenstoff-Fußabdrucks der Region.
|
||||
|
||||
Diese Erweiterung kann von einem Benutzer ad hoc aufgerufen werden, sobald ein API-Schlüssel und ein Regionscode in ein Formular eingegeben wurden, um den lokalen Stromverbrauch zu bestimmen und so Daten bereitzustellen, die die Stromentscheidungen eines Benutzers beeinflussen können. Zum Beispiel könnte es sinnvoll sein, das Einschalten eines Wäschetrockners (eine kohlenstoffintensive Aktivität) während einer Zeit mit hohem Stromverbrauch in Ihrer Region zu verschieben.
|
||||
|
||||
### Themen
|
||||
|
||||
1. [Über den Browser](1-about-browsers/README.md)
|
||||
2. [Formulare und lokaler Speicher](2-forms-browsers-local-storage/README.md)
|
||||
3. [Hintergrundaufgaben und Leistung](3-background-tasks-and-performance/README.md)
|
||||
|
||||
### Credits
|
||||
|
||||

|
||||
|
||||
## Credits
|
||||
|
||||
Die Idee für diesen Web-Kohlenstoff-Auslöser wurde von Asim Hussain, Leiter des Green Cloud Advocacy Teams bei Microsoft und Autor der [Green Principles](https://principles.green/), vorgeschlagen. Ursprünglich war es ein [Webseitenprojekt](https://github.com/jlooper/green).
|
||||
|
||||
Die Struktur der Browser-Erweiterung wurde von [Adebola Adenirans COVID-Erweiterung](https://github.com/onedebos/covtension) beeinflusst.
|
||||
|
||||
Das Konzept hinter dem 'Punkt'-Icon-System wurde durch die Icon-Struktur der [Energy Lollipop](https://energylollipop.com/) Browser-Erweiterung für Emissionen in Kalifornien inspiriert.
|
||||
|
||||
Diese Lektionen wurden mit ♥️ von [Jen Looper](https://www.twitter.com/jenlooper) geschrieben.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "fab4e6b4f0efcd587a9029d82991f597",
|
||||
"translation_date": "2025-08-24T13:19:41+00:00",
|
||||
"source_file": "5-browser-extension/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Carbon Trigger Browser-Erweiterung: Fertiger Code
|
||||
|
||||
Verwenden Sie die CO2 Signal API von tmrow, um den Stromverbrauch zu verfolgen, und erstellen Sie eine Browser-Erweiterung, damit Sie direkt in Ihrem Browser eine Erinnerung daran haben, wie hoch der Stromverbrauch in Ihrer Region ist. Die gelegentliche Nutzung dieser Erweiterung hilft Ihnen, Entscheidungen über Ihre Aktivitäten basierend auf diesen Informationen zu treffen.
|
||||
|
||||

|
||||
|
||||
## Erste Schritte
|
||||
|
||||
Sie müssen [npm](https://npmjs.com) installiert haben. Laden Sie eine Kopie dieses Codes in einen Ordner auf Ihrem Computer herunter.
|
||||
|
||||
Installieren Sie alle erforderlichen Pakete:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Bauen Sie die Erweiterung mit Webpack:
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Um die Erweiterung in Edge zu installieren, verwenden Sie das Menü mit den 'drei Punkten' in der oberen rechten Ecke des Browsers, um das Erweiterungs-Panel zu finden. Wählen Sie dort 'Entpackte Erweiterung laden', um eine neue Erweiterung zu laden. Öffnen Sie den Ordner 'dist' bei der Aufforderung, und die Erweiterung wird geladen. Um sie zu verwenden, benötigen Sie einen API-Schlüssel für die CO2 Signal API ([hier per E-Mail anfordern](https://www.co2signal.com/) - geben Sie Ihre E-Mail-Adresse in das Feld auf dieser Seite ein) und den [Code für Ihre Region](http://api.electricitymap.org/v3/zones), der der [Electricity Map](https://www.electricitymap.org/map) entspricht (in Boston verwende ich zum Beispiel 'US-NEISO').
|
||||
|
||||

|
||||
|
||||
Sobald der API-Schlüssel und die Region in die Benutzeroberfläche der Erweiterung eingegeben wurden, sollte sich der farbige Punkt in der Browser-Erweiterungsleiste ändern, um den Energieverbrauch Ihrer Region widerzuspiegeln und Ihnen Hinweise darauf zu geben, welche energieintensiven Aktivitäten für Sie angemessen wären. Das Konzept hinter diesem 'Punkt'-System wurde mir von der [Energy Lollipop-Erweiterung](https://energylollipop.com/) für Emissionen in Kalifornien inspiriert.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "cbaf73f94a9ab4c680a10ef871e92948",
|
||||
"translation_date": "2025-08-24T13:20:36+00:00",
|
||||
"source_file": "5-browser-extension/solution/translation/README.es.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Browser-Erweiterung Carbon Trigger: Vollständiger Code
|
||||
|
||||
Mit der CO2-Signal-API von tmrow, die den Stromverbrauch verfolgt, können Sie eine Browser-Erweiterung erstellen, die Ihnen direkt in Ihrem Browser eine Erinnerung an den Stromverbrauch Ihrer Region gibt. Die Nutzung dieser Ad-hoc-Erweiterung hilft Ihnen, Entscheidungen über Ihre Aktivitäten basierend auf diesen Informationen zu treffen.
|
||||
|
||||

|
||||
|
||||
## Erste Schritte
|
||||
|
||||
Sie müssen [npm](https://npmjs.com) installiert haben. Laden Sie eine Kopie dieses Codes in einen Ordner auf Ihrem Computer herunter.
|
||||
|
||||
Installieren Sie alle erforderlichen Pakete:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Bauen Sie die Erweiterung mit webpack:
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Um die Erweiterung in Edge zu installieren, verwenden Sie das Menü mit den 'drei Punkten' in der oberen rechten Ecke des Browsers, um das Erweiterungs-Panel zu finden. Wählen Sie dort 'Entpackt laden', um eine neue Erweiterung zu installieren. Öffnen Sie den Ordner 'dist', wenn Sie dazu aufgefordert werden, und die Erweiterung wird geladen. Um sie zu verwenden, benötigen Sie einen API-Schlüssel für die CO2-Signal-API ([hier per E-Mail anfordern](https://www.co2signal.com/) - geben Sie Ihre E-Mail-Adresse in das Feld auf dieser Seite ein) und den [Code für Ihre Region](http://api.electricitymap.org/v3/zones), der dem [Electricity Map](https://www.electricitymap.org/map) entspricht (in Boston verwende ich beispielsweise 'US-NEISO').
|
||||
|
||||

|
||||
|
||||
Sobald der API-Schlüssel und die Region in der Erweiterungsoberfläche eingegeben wurden, sollte sich der Farbpunktsymbol in der Browser-Erweiterungsleiste ändern, um den Energieverbrauch Ihrer Region widerzuspiegeln und Ihnen einen Hinweis darauf zu geben, welche energieintensiven Aktivitäten für Sie geeignet wären. Die Idee hinter diesem "Punkt"-System stammt von der [Energy Lollipop-Erweiterung](https://energylollipop.com/) für die Emissionen in Kalifornien.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "26fd39046d264ba185dcb086d3a8cf3e",
|
||||
"translation_date": "2025-08-24T13:12:06+00:00",
|
||||
"source_file": "5-browser-extension/start/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Carbon Trigger Browser-Erweiterung: Starter-Code
|
||||
|
||||
Verwenden Sie die CO2 Signal API von tmrow, um den Stromverbrauch zu verfolgen, und erstellen Sie eine Browser-Erweiterung, damit Sie direkt in Ihrem Browser eine Erinnerung daran haben, wie stark der Stromverbrauch in Ihrer Region ist. Die gelegentliche Nutzung dieser Erweiterung hilft Ihnen, Entscheidungen über Ihre Aktivitäten basierend auf diesen Informationen zu treffen.
|
||||
|
||||

|
||||
|
||||
## Erste Schritte
|
||||
|
||||
Sie müssen [npm](https://npmjs.com) installiert haben. Laden Sie eine Kopie dieses Codes in einen Ordner auf Ihrem Computer herunter.
|
||||
|
||||
Installieren Sie alle erforderlichen Pakete:
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Bauen Sie die Erweiterung mit Webpack:
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
Um die Erweiterung in Edge zu installieren, verwenden Sie das Menü mit den 'drei Punkten' in der oberen rechten Ecke des Browsers, um das Erweiterungs-Panel zu finden. Wählen Sie dort 'Entpackt laden', um eine neue Erweiterung zu laden. Öffnen Sie den Ordner 'dist' bei der Aufforderung, und die Erweiterung wird geladen. Um sie zu verwenden, benötigen Sie einen API-Schlüssel für die CO2 Signal API ([hier per E-Mail anfordern](https://www.co2signal.com/) - geben Sie Ihre E-Mail-Adresse in das Feld auf dieser Seite ein) und den [Code für Ihre Region](http://api.electricitymap.org/v3/zones), der der [Electricity Map](https://www.electricitymap.org/map) entspricht (in Boston verwende ich zum Beispiel 'US-NEISO').
|
||||
|
||||

|
||||
|
||||
Sobald der API-Schlüssel und die Region in die Erweiterungsschnittstelle eingegeben wurden, sollte sich der farbige Punkt in der Browser-Erweiterungsleiste ändern, um den Energieverbrauch Ihrer Region widerzuspiegeln, und Ihnen Hinweise darauf geben, welche energieintensiven Aktivitäten für Sie angemessen wären. Das Konzept hinter diesem 'Punkt'-System wurde mir von der [Energy Lollipop-Erweiterung](https://energylollipop.com/) für Emissionen in Kalifornien inspiriert.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,236 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "d9da6dc61fb712b29f65e108c79b8a5d",
|
||||
"translation_date": "2025-08-24T12:40:15+00:00",
|
||||
"source_file": "6-space-game/1-introduction/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Baue ein Weltraumspiel Teil 1: Einführung
|
||||
|
||||

|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/29)
|
||||
|
||||
### Vererbung und Komposition in der Spieleentwicklung
|
||||
|
||||
In den vorherigen Lektionen war es nicht notwendig, sich Gedanken über die Architektur der Apps zu machen, da die Projekte sehr klein waren. Wenn jedoch deine Anwendungen größer werden, werden architektonische Entscheidungen immer wichtiger. Es gibt zwei Hauptansätze, um größere Anwendungen in JavaScript zu erstellen: *Komposition* oder *Vererbung*. Beide haben Vor- und Nachteile, aber wir erklären sie im Kontext eines Spiels.
|
||||
|
||||
✅ Eines der bekanntesten Programmierbücher aller Zeiten beschäftigt sich mit [Design Patterns](https://en.wikipedia.org/wiki/Design_Patterns).
|
||||
|
||||
In einem Spiel gibt es `Spielobjekte`, die Objekte sind, die auf einem Bildschirm existieren. Das bedeutet, dass sie eine Position in einem kartesischen Koordinatensystem haben, charakterisiert durch `x`- und `y`-Koordinaten. Während du ein Spiel entwickelst, wirst du feststellen, dass alle deine Spielobjekte eine Standard-Eigenschaft haben, die für jedes Spiel, das du erstellst, gleich ist. Diese Elemente sind:
|
||||
|
||||
- **positionsbasiert** Die meisten, wenn nicht alle, Spielelemente sind positionsbasiert. Das bedeutet, dass sie eine Position haben, ein `x` und ein `y`.
|
||||
- **beweglich** Dies sind Objekte, die sich an eine neue Position bewegen können. Typischerweise handelt es sich um einen Helden, ein Monster oder einen NPC (einen Nicht-Spieler-Charakter), aber nicht z. B. um ein statisches Objekt wie einen Baum.
|
||||
- **selbstzerstörend** Diese Objekte existieren nur für eine bestimmte Zeit, bevor sie sich selbst zur Löschung vorbereiten. Dies wird normalerweise durch ein `dead`- oder `destroyed`-Boolean dargestellt, das der Spiel-Engine signalisiert, dass dieses Objekt nicht mehr gerendert werden soll.
|
||||
- **Abklingzeit** 'Abklingzeit' ist eine typische Eigenschaft von kurzlebigen Objekten. Ein typisches Beispiel ist ein Textstück oder ein grafischer Effekt wie eine Explosion, die nur für ein paar Millisekunden sichtbar sein soll.
|
||||
|
||||
✅ Denke an ein Spiel wie Pac-Man. Kannst du die vier oben genannten Objekttypen in diesem Spiel identifizieren?
|
||||
|
||||
### Verhalten ausdrücken
|
||||
|
||||
Alles, was wir oben beschrieben haben, sind Verhaltensweisen, die Spielobjekte haben können. Aber wie kodieren wir diese? Wir können dieses Verhalten als Methoden ausdrücken, die entweder Klassen oder Objekten zugeordnet sind.
|
||||
|
||||
**Klassen**
|
||||
|
||||
Die Idee ist, `Klassen` in Verbindung mit `Vererbung` zu verwenden, um einer Klasse ein bestimmtes Verhalten hinzuzufügen.
|
||||
|
||||
✅ Vererbung ist ein wichtiges Konzept, das es zu verstehen gilt. Erfahre mehr im [MDN-Artikel über Vererbung](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
|
||||
|
||||
In Code ausgedrückt, könnte ein Spielobjekt typischerweise so aussehen:
|
||||
|
||||
```javascript
|
||||
|
||||
//set up the class GameObject
|
||||
class GameObject {
|
||||
constructor(x, y, type) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
//this class will extend the GameObject's inherent class properties
|
||||
class Movable extends GameObject {
|
||||
constructor(x,y, type) {
|
||||
super(x,y, type)
|
||||
}
|
||||
|
||||
//this movable object can be moved on the screen
|
||||
moveTo(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
//this is a specific class that extends the Movable class, so it can take advantage of all the properties that it inherits
|
||||
class Hero extends Movable {
|
||||
constructor(x,y) {
|
||||
super(x,y, 'Hero')
|
||||
}
|
||||
}
|
||||
|
||||
//this class, on the other hand, only inherits the GameObject properties
|
||||
class Tree extends GameObject {
|
||||
constructor(x,y) {
|
||||
super(x,y, 'Tree')
|
||||
}
|
||||
}
|
||||
|
||||
//a hero can move...
|
||||
const hero = new Hero();
|
||||
hero.moveTo(5,5);
|
||||
|
||||
//but a tree cannot
|
||||
const tree = new Tree();
|
||||
```
|
||||
|
||||
✅ Nimm dir ein paar Minuten Zeit, um dir einen Pac-Man-Helden (z. B. Inky, Pinky oder Blinky) vorzustellen und wie er in JavaScript geschrieben werden könnte.
|
||||
|
||||
**Komposition**
|
||||
|
||||
Ein anderer Ansatz zur Handhabung von Objektvererbung ist die Verwendung von *Komposition*. Dabei drücken Objekte ihr Verhalten so aus:
|
||||
|
||||
```javascript
|
||||
//create a constant gameObject
|
||||
const gameObject = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
type: ''
|
||||
};
|
||||
|
||||
//...and a constant movable
|
||||
const movable = {
|
||||
moveTo(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
//then the constant movableObject is composed of the gameObject and movable constants
|
||||
const movableObject = {...gameObject, ...movable};
|
||||
|
||||
//then create a function to create a new Hero who inherits the movableObject properties
|
||||
function createHero(x, y) {
|
||||
return {
|
||||
...movableObject,
|
||||
x,
|
||||
y,
|
||||
type: 'Hero'
|
||||
}
|
||||
}
|
||||
//...and a static object that inherits only the gameObject properties
|
||||
function createStatic(x, y, type) {
|
||||
return {
|
||||
...gameObject
|
||||
x,
|
||||
y,
|
||||
type
|
||||
}
|
||||
}
|
||||
//create the hero and move it
|
||||
const hero = createHero(10,10);
|
||||
hero.moveTo(5,5);
|
||||
//and create a static tree which only stands around
|
||||
const tree = createStatic(0,0, 'Tree');
|
||||
```
|
||||
|
||||
**Welches Muster sollte ich verwenden?**
|
||||
|
||||
Es liegt an dir, welches Muster du wählst. JavaScript unterstützt beide Paradigmen.
|
||||
|
||||
--
|
||||
|
||||
Ein weiteres Muster, das in der Spieleentwicklung häufig vorkommt, befasst sich mit der Benutzererfahrung und der Leistung des Spiels.
|
||||
|
||||
## Pub/Sub-Muster
|
||||
|
||||
✅ Pub/Sub steht für 'Publish-Subscribe' (Veröffentlichen-Abonnieren)
|
||||
|
||||
Dieses Muster behandelt die Idee, dass die verschiedenen Teile deiner Anwendung nichts voneinander wissen sollten. Warum? Es macht es viel einfacher, den Überblick zu behalten, wenn die verschiedenen Teile getrennt sind. Außerdem wird es einfacher, das Verhalten bei Bedarf plötzlich zu ändern. Wie erreichen wir das? Indem wir einige Konzepte einführen:
|
||||
|
||||
- **Nachricht**: Eine Nachricht ist normalerweise ein Textstring, begleitet von einer optionalen Nutzlast (ein Datenstück, das klärt, worum es bei der Nachricht geht). Eine typische Nachricht in einem Spiel könnte `KEY_PRESSED_ENTER` sein.
|
||||
- **Publisher**: Dieses Element *veröffentlicht* eine Nachricht und sendet sie an alle Abonnenten.
|
||||
- **Subscriber**: Dieses Element *hört* auf bestimmte Nachrichten und führt als Reaktion auf den Empfang dieser Nachricht eine Aufgabe aus, z. B. das Abfeuern eines Lasers.
|
||||
|
||||
Die Implementierung ist recht klein, aber es ist ein sehr mächtiges Muster. So kann es implementiert werden:
|
||||
|
||||
```javascript
|
||||
//set up an EventEmitter class that contains listeners
|
||||
class EventEmitter {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
//when a message is received, let the listener to handle its payload
|
||||
on(message, listener) {
|
||||
if (!this.listeners[message]) {
|
||||
this.listeners[message] = [];
|
||||
}
|
||||
this.listeners[message].push(listener);
|
||||
}
|
||||
//when a message is sent, send it to a listener with some payload
|
||||
emit(message, payload = null) {
|
||||
if (this.listeners[message]) {
|
||||
this.listeners[message].forEach(l => l(message, payload))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Um den obigen Code zu verwenden, können wir eine sehr kleine Implementierung erstellen:
|
||||
|
||||
```javascript
|
||||
//set up a message structure
|
||||
const Messages = {
|
||||
HERO_MOVE_LEFT: 'HERO_MOVE_LEFT'
|
||||
};
|
||||
//invoke the eventEmitter you set up above
|
||||
const eventEmitter = new EventEmitter();
|
||||
//set up a hero
|
||||
const hero = createHero(0,0);
|
||||
//let the eventEmitter know to watch for messages pertaining to the hero moving left, and act on it
|
||||
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
|
||||
hero.move(5,0);
|
||||
});
|
||||
|
||||
//set up the window to listen for the keyup event, specifically if the left arrow is hit, emit a message to move the hero left
|
||||
window.addEventListener('keyup', (evt) => {
|
||||
if (evt.key === 'ArrowLeft') {
|
||||
eventEmitter.emit(Messages.HERO_MOVE_LEFT)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Oben verbinden wir ein Tastaturereignis, `ArrowLeft`, und senden die Nachricht `HERO_MOVE_LEFT`. Wir hören auf diese Nachricht und bewegen den `Helden` als Ergebnis. Die Stärke dieses Musters liegt darin, dass der Event-Listener und der Held nichts voneinander wissen. Du kannst `ArrowLeft` auf die Taste `A` umlegen. Außerdem wäre es möglich, bei `ArrowLeft` etwas völlig anderes zu tun, indem du ein paar Änderungen an der `on`-Funktion des EventEmitters vornimmst:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
|
||||
hero.move(5,0);
|
||||
});
|
||||
```
|
||||
|
||||
Wenn dein Spiel wächst und komplexer wird, bleibt dieses Muster gleich in seiner Komplexität und dein Code bleibt sauber. Es wird wirklich empfohlen, dieses Muster zu übernehmen.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Überlege, wie das Pub-Sub-Muster ein Spiel verbessern kann. Welche Teile sollten Ereignisse auslösen, und wie sollte das Spiel darauf reagieren? Jetzt hast du die Chance, kreativ zu werden und dir ein neues Spiel auszudenken, sowie das Verhalten seiner Teile zu planen.
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/30)
|
||||
|
||||
## Rückblick & Selbststudium
|
||||
|
||||
Erfahre mehr über Pub/Sub, indem du [darüber liest](https://docs.microsoft.com/azure/architecture/patterns/publisher-subscriber/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Entwirf ein Spiel](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "009bdedee9cc82988264be8cb31f9bf4",
|
||||
"translation_date": "2025-08-24T12:41:44+00:00",
|
||||
"source_file": "6-space-game/1-introduction/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Entwerfe ein Spiel
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Nutze die Codebeispiele aus der Lektion, um eine Darstellung eines Spiels zu schreiben, das dir gefällt. Es sollte ein einfaches Spiel sein, aber das Ziel ist es, entweder das Klassen- oder das Kompositionsmuster sowie das Pub/Sub-Muster zu verwenden, um zu zeigen, wie ein Spiel gestartet werden könnte. Werde kreativ!
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | -------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------- |
|
||||
| | Drei Elemente werden auf dem Bildschirm platziert und manipuliert | Zwei Elemente werden auf dem Bildschirm platziert und manipuliert | Ein Element wird auf dem Bildschirm platziert und manipuliert |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "ca1cf78a4c60df77ab32a154ec024d7f",
|
||||
"translation_date": "2025-08-24T12:35:34+00:00",
|
||||
"source_file": "6-space-game/2-drawing-to-canvas/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Experimentiere mit der Canvas-API
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Wähle ein Element der Canvas-API aus und gestalte etwas Interessantes damit. Kannst du eine kleine Galaxie aus wiederholten Sternen erschaffen? Kannst du eine interessante Textur aus farbigen Linien erstellen? Du kannst dir auf CodePen Inspiration holen (aber nicht kopieren).
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | -------------------------------------------------------- | ----------------------------------- | --------------------- |
|
||||
| | Code wird eingereicht und zeigt eine interessante Textur oder Form | Code wird eingereicht, läuft aber nicht | Code wird nicht eingereicht |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,400 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "23f088add24f0f1fa51014a9e27ea280",
|
||||
"translation_date": "2025-08-24T12:30:47+00:00",
|
||||
"source_file": "6-space-game/3-moving-elements-around/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Baue ein Weltraumspiel Teil 3: Bewegung hinzufügen
|
||||
|
||||
## Quiz vor der Lektion
|
||||
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/33)
|
||||
|
||||
Spiele machen erst dann richtig Spaß, wenn Aliens über den Bildschirm laufen! In diesem Spiel werden wir zwei Arten von Bewegungen nutzen:
|
||||
|
||||
- **Tastatur-/Mausbewegung**: wenn der Benutzer mit der Tastatur oder Maus interagiert, um ein Objekt auf dem Bildschirm zu bewegen.
|
||||
- **Spielinduzierte Bewegung**: wenn das Spiel ein Objekt in bestimmten Zeitintervallen bewegt.
|
||||
|
||||
Wie bewegt man also Dinge auf einem Bildschirm? Es dreht sich alles um kartesische Koordinaten: Wir ändern die Position (x, y) des Objekts und zeichnen dann den Bildschirm neu.
|
||||
|
||||
Typischerweise sind folgende Schritte notwendig, um *Bewegung* auf einem Bildschirm zu realisieren:
|
||||
|
||||
1. **Setze eine neue Position** für ein Objekt; dies ist notwendig, damit das Objekt als bewegt wahrgenommen wird.
|
||||
2. **Leere den Bildschirm**, der Bildschirm muss zwischen den Zeichnungen geleert werden. Dies kann durch das Zeichnen eines Rechtecks mit einer Hintergrundfarbe erfolgen.
|
||||
3. **Zeichne das Objekt neu** an der neuen Position. Dadurch wird das Objekt schließlich von einer Position zur anderen bewegt.
|
||||
|
||||
So könnte das im Code aussehen:
|
||||
|
||||
```javascript
|
||||
//set the hero's location
|
||||
hero.x += 5;
|
||||
// clear the rectangle that hosts the hero
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// redraw the game background and hero
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||
ctx.fillStyle = "black";
|
||||
ctx.drawImage(heroImg, hero.x, hero.y);
|
||||
```
|
||||
|
||||
✅ Kannst du dir vorstellen, warum das Neuzeichnen deines Helden viele Male pro Sekunde zu Leistungseinbußen führen könnte? Lies mehr über [Alternativen zu diesem Muster](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas).
|
||||
|
||||
## Tastaturereignisse behandeln
|
||||
|
||||
Ereignisse werden behandelt, indem spezifische Ereignisse mit Code verknüpft werden. Tastaturereignisse werden für das gesamte Fenster ausgelöst, während Mausereignisse wie ein `click` mit einem bestimmten Element verbunden werden können. In diesem Projekt werden wir Tastaturereignisse verwenden.
|
||||
|
||||
Um ein Ereignis zu behandeln, musst du die Methode `addEventListener()` des Fensters verwenden und ihr zwei Eingabeparameter übergeben. Der erste Parameter ist der Name des Ereignisses, z. B. `keyup`. Der zweite Parameter ist die Funktion, die als Ergebnis des Ereignisses aufgerufen werden soll.
|
||||
|
||||
Hier ist ein Beispiel:
|
||||
|
||||
```javascript
|
||||
window.addEventListener('keyup', (evt) => {
|
||||
// `evt.key` = string representation of the key
|
||||
if (evt.key === 'ArrowUp') {
|
||||
// do something
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Für Tastaturereignisse gibt es zwei Eigenschaften des Ereignisses, die du verwenden kannst, um zu sehen, welche Taste gedrückt wurde:
|
||||
|
||||
- `key`, dies ist eine String-Darstellung der gedrückten Taste, z. B. `ArrowUp`.
|
||||
- `keyCode`, dies ist eine numerische Darstellung, z. B. `37`, was `ArrowLeft` entspricht.
|
||||
|
||||
✅ Die Manipulation von Tastaturereignissen ist auch außerhalb der Spieleentwicklung nützlich. Welche anderen Anwendungen kannst du dir für diese Technik vorstellen?
|
||||
|
||||
### Besondere Tasten: ein Hinweis
|
||||
|
||||
Es gibt einige *besondere* Tasten, die das Fenster beeinflussen. Das bedeutet, dass, wenn du ein `keyup`-Ereignis hörst und diese besonderen Tasten benutzt, um deinen Helden zu bewegen, auch ein horizontales Scrollen ausgelöst wird. Aus diesem Grund möchtest du möglicherweise dieses eingebaute Browserverhalten *deaktivieren*, während du dein Spiel entwickelst. Dafür benötigst du Code wie diesen:
|
||||
|
||||
```javascript
|
||||
let onKeyDown = function (e) {
|
||||
console.log(e.keyCode);
|
||||
switch (e.keyCode) {
|
||||
case 37:
|
||||
case 39:
|
||||
case 38:
|
||||
case 40: // Arrow keys
|
||||
case 32:
|
||||
e.preventDefault();
|
||||
break; // Space
|
||||
default:
|
||||
break; // do not block other keys
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', onKeyDown);
|
||||
```
|
||||
|
||||
Der obige Code stellt sicher, dass die Pfeiltasten und die Leertaste ihr *Standardverhalten* deaktivieren. Der Mechanismus zur Deaktivierung erfolgt, wenn wir `e.preventDefault()` aufrufen.
|
||||
|
||||
## Spielinduzierte Bewegung
|
||||
|
||||
Wir können Dinge von selbst bewegen, indem wir Timer wie die Funktionen `setTimeout()` oder `setInterval()` verwenden, die die Position des Objekts bei jedem Tick oder Zeitintervall aktualisieren. So könnte das aussehen:
|
||||
|
||||
```javascript
|
||||
let id = setInterval(() => {
|
||||
//move the enemy on the y axis
|
||||
enemy.y += 10;
|
||||
})
|
||||
```
|
||||
|
||||
## Die Spielschleife
|
||||
|
||||
Die Spielschleife ist ein Konzept, das im Wesentlichen eine Funktion ist, die in regelmäßigen Abständen aufgerufen wird. Sie wird als Spielschleife bezeichnet, da alles, was für den Benutzer sichtbar sein soll, in der Schleife gezeichnet wird. Die Spielschleife verwendet alle Spielobjekte, die Teil des Spiels sind, und zeichnet sie, es sei denn, sie sollten aus irgendeinem Grund nicht mehr Teil des Spiels sein. Zum Beispiel, wenn ein Objekt ein Feind ist, der von einem Laser getroffen wird und explodiert, ist es nicht mehr Teil der aktuellen Spielschleife (du wirst mehr darüber in den nächsten Lektionen lernen).
|
||||
|
||||
So könnte eine Spielschleife typischerweise im Code aussehen:
|
||||
|
||||
```javascript
|
||||
let gameLoopId = setInterval(() =>
|
||||
function gameLoop() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawHero();
|
||||
drawEnemies();
|
||||
drawStaticObjects();
|
||||
}, 200);
|
||||
```
|
||||
|
||||
Die obige Schleife wird alle `200` Millisekunden aufgerufen, um die Leinwand neu zu zeichnen. Du kannst das Intervall wählen, das für dein Spiel am sinnvollsten ist.
|
||||
|
||||
## Fortsetzung des Weltraumspiels
|
||||
|
||||
Du wirst den bestehenden Code erweitern. Entweder beginnst du mit dem Code, den du in Teil I abgeschlossen hast, oder du verwendest den Code aus [Teil II - Starter](../../../../6-space-game/3-moving-elements-around/your-work).
|
||||
|
||||
- **Bewegung des Helden**: Du wirst Code hinzufügen, um sicherzustellen, dass du den Helden mit den Pfeiltasten bewegen kannst.
|
||||
- **Bewegung der Feinde**: Du wirst auch Code hinzufügen, um sicherzustellen, dass sich die Feinde mit einer bestimmten Geschwindigkeit von oben nach unten bewegen.
|
||||
|
||||
## Empfohlene Schritte
|
||||
|
||||
Finde die Dateien, die für dich im Unterordner `your-work` erstellt wurden. Sie sollten Folgendes enthalten:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Starte dein Projekt im Ordner `your_work`, indem du Folgendes eingibst:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Das obige startet einen HTTP-Server unter der Adresse `http://localhost:5000`. Öffne einen Browser und gib diese Adresse ein. Im Moment sollten der Held und alle Feinde angezeigt werden; noch bewegt sich nichts!
|
||||
|
||||
### Code hinzufügen
|
||||
|
||||
1. **Füge dedizierte Objekte** für `hero`, `enemy` und `game object` hinzu, die `x`- und `y`-Eigenschaften haben. (Erinnere dich an den Abschnitt über [Vererbung oder Komposition](../README.md)).
|
||||
|
||||
*TIPP*: `game object` sollte das Objekt sein, das `x` und `y` sowie die Fähigkeit hat, sich selbst auf eine Leinwand zu zeichnen.
|
||||
|
||||
> Tipp: Beginne damit, eine neue GameObject-Klasse mit ihrem Konstruktor wie unten dargestellt hinzuzufügen, und zeichne sie dann auf die Leinwand:
|
||||
|
||||
```javascript
|
||||
|
||||
class GameObject {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.dead = false;
|
||||
this.type = "";
|
||||
this.width = 0;
|
||||
this.height = 0;
|
||||
this.img = undefined;
|
||||
}
|
||||
|
||||
draw(ctx) {
|
||||
ctx.drawImage(this.img, this.x, this.y, this.width, this.height);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Erweitere nun dieses GameObject, um den Helden und den Feind zu erstellen.
|
||||
|
||||
```javascript
|
||||
class Hero extends GameObject {
|
||||
constructor(x, y) {
|
||||
...it needs an x, y, type, and speed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
class Enemy extends GameObject {
|
||||
constructor(x, y) {
|
||||
super(x, y);
|
||||
(this.width = 98), (this.height = 50);
|
||||
this.type = "Enemy";
|
||||
let id = setInterval(() => {
|
||||
if (this.y < canvas.height - this.height) {
|
||||
this.y += 5;
|
||||
} else {
|
||||
console.log('Stopped at', this.y)
|
||||
clearInterval(id);
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Füge Ereignis-Handler für Tasten** hinzu, um die Navigation (Bewegung des Helden nach oben/unten, links/rechts) zu steuern.
|
||||
|
||||
*DENKE DARAN*: Es handelt sich um ein kartesisches System, oben links ist `0,0`. Denke auch daran, Code hinzuzufügen, um das *Standardverhalten* zu deaktivieren.
|
||||
|
||||
> Tipp: Erstelle deine onKeyDown-Funktion und verknüpfe sie mit dem Fenster:
|
||||
|
||||
```javascript
|
||||
let onKeyDown = function (e) {
|
||||
console.log(e.keyCode);
|
||||
...add the code from the lesson above to stop default behavior
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", onKeyDown);
|
||||
```
|
||||
|
||||
Überprüfe zu diesem Zeitpunkt die Konsole deines Browsers und beobachte, wie die Tastenanschläge protokolliert werden.
|
||||
|
||||
3. **Implementiere** das [Pub-Sub-Muster](../README.md), um deinen Code sauber zu halten, während du die verbleibenden Teile umsetzt.
|
||||
|
||||
Um diesen letzten Teil umzusetzen, kannst du:
|
||||
|
||||
1. **Einen Ereignis-Listener** für das Fenster hinzufügen:
|
||||
|
||||
```javascript
|
||||
window.addEventListener("keyup", (evt) => {
|
||||
if (evt.key === "ArrowUp") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_UP);
|
||||
} else if (evt.key === "ArrowDown") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_DOWN);
|
||||
} else if (evt.key === "ArrowLeft") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_LEFT);
|
||||
} else if (evt.key === "ArrowRight") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_RIGHT);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
1. **Eine EventEmitter-Klasse erstellen**, um Nachrichten zu veröffentlichen und zu abonnieren:
|
||||
|
||||
```javascript
|
||||
class EventEmitter {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
}
|
||||
|
||||
on(message, listener) {
|
||||
if (!this.listeners[message]) {
|
||||
this.listeners[message] = [];
|
||||
}
|
||||
this.listeners[message].push(listener);
|
||||
}
|
||||
|
||||
emit(message, payload = null) {
|
||||
if (this.listeners[message]) {
|
||||
this.listeners[message].forEach((l) => l(message, payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. **Konstanten hinzufügen** und den EventEmitter einrichten:
|
||||
|
||||
```javascript
|
||||
const Messages = {
|
||||
KEY_EVENT_UP: "KEY_EVENT_UP",
|
||||
KEY_EVENT_DOWN: "KEY_EVENT_DOWN",
|
||||
KEY_EVENT_LEFT: "KEY_EVENT_LEFT",
|
||||
KEY_EVENT_RIGHT: "KEY_EVENT_RIGHT",
|
||||
};
|
||||
|
||||
let heroImg,
|
||||
enemyImg,
|
||||
laserImg,
|
||||
canvas, ctx,
|
||||
gameObjects = [],
|
||||
hero,
|
||||
eventEmitter = new EventEmitter();
|
||||
```
|
||||
|
||||
1. **Das Spiel initialisieren**
|
||||
|
||||
```javascript
|
||||
function initGame() {
|
||||
gameObjects = [];
|
||||
createEnemies();
|
||||
createHero();
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_UP, () => {
|
||||
hero.y -=5 ;
|
||||
})
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_DOWN, () => {
|
||||
hero.y += 5;
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_LEFT, () => {
|
||||
hero.x -= 5;
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.KEY_EVENT_RIGHT, () => {
|
||||
hero.x += 5;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
1. **Richte die Spielschleife ein**
|
||||
|
||||
Refaktoriere die window.onload-Funktion, um das Spiel zu initialisieren und eine Spielschleife in einem geeigneten Intervall einzurichten. Du wirst auch einen Laserstrahl hinzufügen:
|
||||
|
||||
```javascript
|
||||
window.onload = async () => {
|
||||
canvas = document.getElementById("canvas");
|
||||
ctx = canvas.getContext("2d");
|
||||
heroImg = await loadTexture("assets/player.png");
|
||||
enemyImg = await loadTexture("assets/enemyShip.png");
|
||||
laserImg = await loadTexture("assets/laserRed.png");
|
||||
|
||||
initGame();
|
||||
let gameLoopId = setInterval(() => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawGameObjects(ctx);
|
||||
}, 100)
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
5. **Füge Code hinzu**, um Feinde in bestimmten Intervallen zu bewegen.
|
||||
|
||||
Refaktoriere die Funktion `createEnemies()`, um die Feinde zu erstellen und sie in die neue GameObjects-Klasse zu schieben:
|
||||
|
||||
```javascript
|
||||
function createEnemies() {
|
||||
const MONSTER_TOTAL = 5;
|
||||
const MONSTER_WIDTH = MONSTER_TOTAL * 98;
|
||||
const START_X = (canvas.width - MONSTER_WIDTH) / 2;
|
||||
const STOP_X = START_X + MONSTER_WIDTH;
|
||||
|
||||
for (let x = START_X; x < STOP_X; x += 98) {
|
||||
for (let y = 0; y < 50 * 5; y += 50) {
|
||||
const enemy = new Enemy(x, y);
|
||||
enemy.img = enemyImg;
|
||||
gameObjects.push(enemy);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
und füge eine Funktion `createHero()` hinzu, um einen ähnlichen Prozess für den Helden durchzuführen.
|
||||
|
||||
```javascript
|
||||
function createHero() {
|
||||
hero = new Hero(
|
||||
canvas.width / 2 - 45,
|
||||
canvas.height - canvas.height / 4
|
||||
);
|
||||
hero.img = heroImg;
|
||||
gameObjects.push(hero);
|
||||
}
|
||||
```
|
||||
|
||||
und schließlich füge eine Funktion `drawGameObjects()` hinzu, um das Zeichnen zu starten:
|
||||
|
||||
```javascript
|
||||
function drawGameObjects(ctx) {
|
||||
gameObjects.forEach(go => go.draw(ctx));
|
||||
}
|
||||
```
|
||||
|
||||
Deine Feinde sollten beginnen, auf dein Raumschiff zuzugehen!
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Wie du sehen kannst, kann dein Code zu einem "Spaghetti-Code" werden, wenn du Funktionen, Variablen und Klassen hinzufügst. Wie kannst du deinen Code besser organisieren, damit er lesbarer wird? Skizziere ein System, um deinen Code zu organisieren, auch wenn er weiterhin in einer Datei bleibt.
|
||||
|
||||
## Quiz nach der Lektion
|
||||
|
||||
[Quiz nach der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/34)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Während wir unser Spiel ohne Frameworks schreiben, gibt es viele JavaScript-basierte Canvas-Frameworks für die Spieleentwicklung. Nimm dir Zeit, um [darüber zu lesen](https://github.com/collections/javascript-game-engines).
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Kommentiere deinen Code](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "ccfcd8c2932761359fbaff3d6b01ace4",
|
||||
"translation_date": "2025-08-24T12:32:53+00:00",
|
||||
"source_file": "6-space-game/3-moving-elements-around/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Kommentiere deinen Code
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Gehe deine aktuelle /app.js-Datei in deinem Spielordner durch und finde Möglichkeiten, sie zu kommentieren und aufzuräumen. Es ist sehr einfach, dass Code außer Kontrolle gerät, und jetzt ist eine gute Gelegenheit, Kommentare hinzuzufügen, um sicherzustellen, dass dein Code lesbar bleibt und du ihn später verwenden kannst.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ------------------------------------------------------------------ | ------------------------------------ | -------------------------------------------------------------- |
|
||||
| | Der `app.js`-Code ist vollständig kommentiert und in logische Blöcke organisiert | Der `app.js`-Code ist ausreichend kommentiert | Der `app.js`-Code ist etwas unorganisiert und es fehlen gute Kommentare |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "8a0a097b45e7c75a611e2795e4013f16",
|
||||
"translation_date": "2025-08-24T12:38:23+00:00",
|
||||
"source_file": "6-space-game/4-collision-detection/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erkunde Kollisionen
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Um besser zu verstehen, wie Kollisionen funktionieren, erstelle ein sehr kleines Spiel mit ein paar Objekten, die kollidieren. Lass sie sich durch Tastendruck oder Mausklicks bewegen und sorge dafür, dass etwas mit einem der Objekte passiert, wenn es getroffen wird. Es könnte zum Beispiel ein Meteorit sein, der die Erde trifft, oder Autoscooter. Sei kreativ!
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Ausreichend | Verbesserungswürdig |
|
||||
| --------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------- |
|
||||
| | Vollständig funktionierender Code wird erstellt, mit Objekten, die auf die Leinwand gezeichnet werden, grundlegenden Kollisionen und Reaktionen | Code ist in irgendeiner Weise unvollständig | Code funktioniert nicht |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:39:26+00:00",
|
||||
"source_file": "6-space-game/4-collision-detection/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:38:59+00:00",
|
||||
"source_file": "6-space-game/4-collision-detection/your-work/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,201 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "4e8250db84b027c9ff816b4e4c093457",
|
||||
"translation_date": "2025-08-24T12:27:27+00:00",
|
||||
"source_file": "6-space-game/5-keeping-score/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Baue ein Weltraumspiel Teil 5: Punkte und Leben
|
||||
|
||||
## Quiz vor der Lektion
|
||||
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/37)
|
||||
|
||||
In dieser Lektion lernst du, wie man Punkte zu einem Spiel hinzufügt und Leben berechnet.
|
||||
|
||||
## Text auf dem Bildschirm anzeigen
|
||||
|
||||
Um den Punktestand eines Spiels auf dem Bildschirm anzuzeigen, musst du wissen, wie man Text auf dem Bildschirm platziert. Die Antwort ist die Methode `fillText()` des Canvas-Objekts. Du kannst auch andere Aspekte steuern, wie die Schriftart, die Farbe des Textes und sogar die Ausrichtung (links, rechts, zentriert). Unten findest du Code, der Text auf dem Bildschirm zeichnet.
|
||||
|
||||
```javascript
|
||||
ctx.font = "30px Arial";
|
||||
ctx.fillStyle = "red";
|
||||
ctx.textAlign = "right";
|
||||
ctx.fillText("show this on the screen", 0, 0);
|
||||
```
|
||||
|
||||
✅ Lies mehr darüber, [wie man Text zu einem Canvas hinzufügt](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_text), und gestalte deinen Text ruhig etwas schicker!
|
||||
|
||||
## Leben als Spielkonzept
|
||||
|
||||
Das Konzept von Leben in einem Spiel ist lediglich eine Zahl. Im Kontext eines Weltraumspiels ist es üblich, eine bestimmte Anzahl von Leben zuzuweisen, die nach und nach abgezogen werden, wenn dein Schiff Schaden nimmt. Es ist schön, wenn man dies grafisch darstellen kann, z. B. mit kleinen Schiffen oder Herzen anstelle einer Zahl.
|
||||
|
||||
## Was soll gebaut werden?
|
||||
|
||||
Füge deinem Spiel Folgendes hinzu:
|
||||
|
||||
- **Punktestand**: Für jedes feindliche Schiff, das zerstört wird, sollte der Held Punkte erhalten. Wir schlagen 100 Punkte pro Schiff vor. Der Punktestand sollte unten links angezeigt werden.
|
||||
- **Leben**: Dein Schiff hat drei Leben. Du verlierst ein Leben, jedes Mal wenn ein feindliches Schiff mit dir kollidiert. Die Lebensanzeige sollte unten rechts angezeigt werden und aus der folgenden Grafik bestehen: .
|
||||
|
||||
## Empfohlene Schritte
|
||||
|
||||
Finde die Dateien, die für dich im Unterordner `your-work` erstellt wurden. Sie sollten Folgendes enthalten:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| laserRed.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Starte dein Projekt im Ordner `your_work`, indem du Folgendes eingibst:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Das oben Genannte startet einen HTTP-Server unter der Adresse `http://localhost:5000`. Öffne einen Browser und gib diese Adresse ein. Derzeit sollten der Held und alle Feinde angezeigt werden, und wenn du die Pfeiltasten links und rechts drückst, bewegt sich der Held und kann Feinde abschießen.
|
||||
|
||||
### Code hinzufügen
|
||||
|
||||
1. **Kopiere die benötigten Assets** aus dem Ordner `solution/assets/` in den Ordner `your-work`; du wirst ein `life.png`-Asset hinzufügen. Füge das `lifeImg` zur Funktion `window.onload` hinzu:
|
||||
|
||||
```javascript
|
||||
lifeImg = await loadTexture("assets/life.png");
|
||||
```
|
||||
|
||||
1. Füge das `lifeImg` zur Liste der Assets hinzu:
|
||||
|
||||
```javascript
|
||||
let heroImg,
|
||||
...
|
||||
lifeImg,
|
||||
...
|
||||
eventEmitter = new EventEmitter();
|
||||
```
|
||||
|
||||
2. **Variablen hinzufügen**. Füge Code hinzu, der deinen Gesamtpunktestand (0) und die verbleibenden Leben (3) darstellt, und zeige diese Werte auf dem Bildschirm an.
|
||||
|
||||
3. **Erweitere die Funktion `updateGameObjects()`**. Erweitere die Funktion `updateGameObjects()`, um Kollisionen mit Feinden zu behandeln:
|
||||
|
||||
```javascript
|
||||
enemies.forEach(enemy => {
|
||||
const heroRect = hero.rectFromGameObject();
|
||||
if (intersectRect(heroRect, enemy.rectFromGameObject())) {
|
||||
eventEmitter.emit(Messages.COLLISION_ENEMY_HERO, { enemy });
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
4. **Füge Leben und Punkte hinzu**.
|
||||
1. **Initialisiere Variablen**. Unter `this.cooldown = 0` in der Klasse `Hero` setze Leben und Punkte:
|
||||
|
||||
```javascript
|
||||
this.life = 3;
|
||||
this.points = 0;
|
||||
```
|
||||
|
||||
1. **Zeichne Variablen auf den Bildschirm**. Zeige diese Werte auf dem Bildschirm an:
|
||||
|
||||
```javascript
|
||||
function drawLife() {
|
||||
// TODO, 35, 27
|
||||
const START_POS = canvas.width - 180;
|
||||
for(let i=0; i < hero.life; i++ ) {
|
||||
ctx.drawImage(
|
||||
lifeImg,
|
||||
START_POS + (45 * (i+1) ),
|
||||
canvas.height - 37);
|
||||
}
|
||||
}
|
||||
|
||||
function drawPoints() {
|
||||
ctx.font = "30px Arial";
|
||||
ctx.fillStyle = "red";
|
||||
ctx.textAlign = "left";
|
||||
drawText("Points: " + hero.points, 10, canvas.height-20);
|
||||
}
|
||||
|
||||
function drawText(message, x, y) {
|
||||
ctx.fillText(message, x, y);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
1. **Füge Methoden zur Spielschleife hinzu**. Stelle sicher, dass du diese Funktionen zur Funktion `window.onload` unter `updateGameObjects()` hinzufügst:
|
||||
|
||||
```javascript
|
||||
drawPoints();
|
||||
drawLife();
|
||||
```
|
||||
|
||||
1. **Implementiere Spielregeln**. Implementiere die folgenden Spielregeln:
|
||||
|
||||
1. **Für jede Kollision zwischen Held und Feind** ziehe ein Leben ab.
|
||||
|
||||
Erweitere die Klasse `Hero`, um diese Abzüge vorzunehmen:
|
||||
|
||||
```javascript
|
||||
decrementLife() {
|
||||
this.life--;
|
||||
if (this.life === 0) {
|
||||
this.dead = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Für jeden Laser, der einen Feind trifft**, erhöhe den Punktestand um 100 Punkte.
|
||||
|
||||
Erweitere die Klasse `Hero`, um diese Erhöhung vorzunehmen:
|
||||
|
||||
```javascript
|
||||
incrementPoints() {
|
||||
this.points += 100;
|
||||
}
|
||||
```
|
||||
|
||||
Füge diese Funktionen zu deinen Collision Event Emitters hinzu:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
||||
first.dead = true;
|
||||
second.dead = true;
|
||||
hero.incrementPoints();
|
||||
})
|
||||
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
|
||||
enemy.dead = true;
|
||||
hero.decrementLife();
|
||||
});
|
||||
```
|
||||
|
||||
✅ Recherchiere ein wenig, um andere Spiele zu entdecken, die mit JavaScript/Canvas erstellt wurden. Was sind ihre gemeinsamen Merkmale?
|
||||
|
||||
Am Ende dieser Arbeit solltest du die kleinen 'Lebens'-Schiffe unten rechts, Punkte unten links sehen und beobachten können, wie deine Lebensanzahl bei Kollisionen mit Feinden abnimmt und deine Punkte steigen, wenn du Feinde abschießt. Gut gemacht! Dein Spiel ist fast fertig.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Dein Code ist fast fertig. Kannst du dir die nächsten Schritte vorstellen?
|
||||
|
||||
## Quiz nach der Lektion
|
||||
|
||||
[Quiz nach der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/38)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Recherchiere einige Möglichkeiten, wie du Punktestände und Leben in einem Spiel erhöhen und verringern kannst. Es gibt einige interessante Spiel-Engines wie [PlayFab](https://playfab.com). Wie könnte die Verwendung einer solchen Engine dein Spiel verbessern?
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Baue ein Punktespiel](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "81f292dbda01685b91735e0398dc0504",
|
||||
"translation_date": "2025-08-24T12:28:47+00:00",
|
||||
"source_file": "6-space-game/5-keeping-score/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstelle ein Punktespiel
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Erstelle ein Spiel, in dem Leben und Punkte auf kreative Weise angezeigt werden. Ein Vorschlag ist, das Leben als Herzen darzustellen und die Punkte als große Zahl im unteren mittleren Bereich des Bildschirms anzuzeigen. Schau dir hier [Kostenlose Spielressourcen](https://www.kenney.nl/) an.
|
||||
|
||||
# Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ---------------------- | --------------------------- | --------------------------- |
|
||||
| | vollständiges Spiel wird präsentiert | Spiel wird teilweise präsentiert | unvollständiges Spiel enthält Fehler |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:29:47+00:00",
|
||||
"source_file": "6-space-game/5-keeping-score/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:29:18+00:00",
|
||||
"source_file": "6-space-game/5-keeping-score/your-work/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,234 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "01336cddd638242e99b133614111ea40",
|
||||
"translation_date": "2025-08-24T12:42:46+00:00",
|
||||
"source_file": "6-space-game/6-end-condition/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Baue ein Weltraumspiel Teil 6: Ende und Neustart
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/39)
|
||||
|
||||
Es gibt verschiedene Möglichkeiten, eine *Endbedingung* in einem Spiel auszudrücken. Es liegt an dir als Ersteller des Spiels zu entscheiden, warum das Spiel endet. Hier sind einige Gründe, wenn wir davon ausgehen, dass wir über das Weltraumspiel sprechen, das du bisher gebaut hast:
|
||||
|
||||
- **`N` feindliche Schiffe wurden zerstört**: Es ist ziemlich üblich, dass ein Spiel in verschiedene Level unterteilt wird, bei denen du `N` feindliche Schiffe zerstören musst, um ein Level abzuschließen.
|
||||
- **Dein Schiff wurde zerstört**: Es gibt definitiv Spiele, bei denen du verlierst, wenn dein Schiff zerstört wird. Eine andere gängige Herangehensweise ist das Konzept von Leben. Jedes Mal, wenn dein Schiff zerstört wird, wird ein Leben abgezogen. Sobald alle Leben verloren sind, verlierst du das Spiel.
|
||||
- **Du hast `N` Punkte gesammelt**: Eine weitere häufige Endbedingung ist das Sammeln von Punkten. Wie du Punkte erhältst, liegt an dir, aber es ist ziemlich üblich, Punkte für verschiedene Aktivitäten zu vergeben, wie das Zerstören eines feindlichen Schiffs oder das Sammeln von Gegenständen, die von zerstörten Objekten *fallen*.
|
||||
- **Ein Level abschließen**: Dies könnte mehrere Bedingungen umfassen, wie `X` zerstörte feindliche Schiffe, `Y` gesammelte Punkte oder vielleicht das Einsammeln eines bestimmten Gegenstands.
|
||||
|
||||
## Neustart
|
||||
|
||||
Wenn Menschen dein Spiel mögen, möchten sie es wahrscheinlich erneut spielen. Sobald das Spiel aus irgendeinem Grund endet, solltest du eine Möglichkeit zum Neustart anbieten.
|
||||
|
||||
✅ Überlege dir, unter welchen Bedingungen ein Spiel endet und wie du aufgefordert wirst, es neu zu starten.
|
||||
|
||||
## Was du bauen sollst
|
||||
|
||||
Du wirst diese Regeln zu deinem Spiel hinzufügen:
|
||||
|
||||
1. **Das Spiel gewinnen**. Sobald alle feindlichen Schiffe zerstört sind, gewinnst du das Spiel. Zeige zusätzlich eine Art Siegesnachricht an.
|
||||
1. **Neustart**. Sobald alle Leben verloren sind oder das Spiel gewonnen wurde, solltest du eine Möglichkeit anbieten, das Spiel neu zu starten. Denk daran! Du musst das Spiel neu initialisieren und den vorherigen Spielzustand löschen.
|
||||
|
||||
## Empfohlene Schritte
|
||||
|
||||
Finde die Dateien, die für dich im Unterordner `your-work` erstellt wurden. Sie sollten Folgendes enthalten:
|
||||
|
||||
```bash
|
||||
-| assets
|
||||
-| enemyShip.png
|
||||
-| player.png
|
||||
-| laserRed.png
|
||||
-| life.png
|
||||
-| index.html
|
||||
-| app.js
|
||||
-| package.json
|
||||
```
|
||||
|
||||
Starte dein Projekt im Ordner `your_work`, indem du Folgendes eingibst:
|
||||
|
||||
```bash
|
||||
cd your-work
|
||||
npm start
|
||||
```
|
||||
|
||||
Das obige startet einen HTTP-Server unter der Adresse `http://localhost:5000`. Öffne einen Browser und gib diese Adresse ein. Dein Spiel sollte spielbereit sein.
|
||||
|
||||
> Tipp: Um Warnungen in Visual Studio Code zu vermeiden, bearbeite die Funktion `window.onload`, sodass sie `gameLoopId` direkt aufruft (ohne `let`), und deklariere `gameLoopId` oben in der Datei unabhängig: `let gameLoopId;`
|
||||
|
||||
### Code hinzufügen
|
||||
|
||||
1. **Endbedingung verfolgen**. Füge Code hinzu, der die Anzahl der Feinde oder ob das Heldenschiff zerstört wurde verfolgt, indem du diese zwei Funktionen hinzufügst:
|
||||
|
||||
```javascript
|
||||
function isHeroDead() {
|
||||
return hero.life <= 0;
|
||||
}
|
||||
|
||||
function isEnemiesDead() {
|
||||
const enemies = gameObjects.filter((go) => go.type === "Enemy" && !go.dead);
|
||||
return enemies.length === 0;
|
||||
}
|
||||
```
|
||||
|
||||
1. **Logik zu Nachrichten-Handlern hinzufügen**. Bearbeite den `eventEmitter`, um diese Bedingungen zu behandeln:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
|
||||
first.dead = true;
|
||||
second.dead = true;
|
||||
hero.incrementPoints();
|
||||
|
||||
if (isEnemiesDead()) {
|
||||
eventEmitter.emit(Messages.GAME_END_WIN);
|
||||
}
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.COLLISION_ENEMY_HERO, (_, { enemy }) => {
|
||||
enemy.dead = true;
|
||||
hero.decrementLife();
|
||||
if (isHeroDead()) {
|
||||
eventEmitter.emit(Messages.GAME_END_LOSS);
|
||||
return; // loss before victory
|
||||
}
|
||||
if (isEnemiesDead()) {
|
||||
eventEmitter.emit(Messages.GAME_END_WIN);
|
||||
}
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.GAME_END_WIN, () => {
|
||||
endGame(true);
|
||||
});
|
||||
|
||||
eventEmitter.on(Messages.GAME_END_LOSS, () => {
|
||||
endGame(false);
|
||||
});
|
||||
```
|
||||
|
||||
1. **Neue Nachrichtentypen hinzufügen**. Füge diese Nachrichten dem Konstantenobjekt hinzu:
|
||||
|
||||
```javascript
|
||||
GAME_END_LOSS: "GAME_END_LOSS",
|
||||
GAME_END_WIN: "GAME_END_WIN",
|
||||
```
|
||||
|
||||
2. **Neustart-Code hinzufügen**. Füge Code hinzu, der das Spiel durch Drücken einer ausgewählten Taste neu startet.
|
||||
|
||||
1. **Auf Tastendruck `Enter` hören**. Bearbeite den EventListener deines Fensters, um auf diesen Tastendruck zu hören:
|
||||
|
||||
```javascript
|
||||
else if(evt.key === "Enter") {
|
||||
eventEmitter.emit(Messages.KEY_EVENT_ENTER);
|
||||
}
|
||||
```
|
||||
|
||||
1. **Neustart-Nachricht hinzufügen**. Füge diese Nachricht deinem Nachrichten-Konstanten hinzu:
|
||||
|
||||
```javascript
|
||||
KEY_EVENT_ENTER: "KEY_EVENT_ENTER",
|
||||
```
|
||||
|
||||
1. **Spielregeln implementieren**. Implementiere die folgenden Spielregeln:
|
||||
|
||||
1. **Spieler-Siegesbedingung**. Wenn alle feindlichen Schiffe zerstört sind, zeige eine Siegesnachricht an.
|
||||
|
||||
1. Erstelle zuerst eine Funktion `displayMessage()`:
|
||||
|
||||
```javascript
|
||||
function displayMessage(message, color = "red") {
|
||||
ctx.font = "30px Arial";
|
||||
ctx.fillStyle = color;
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(message, canvas.width / 2, canvas.height / 2);
|
||||
}
|
||||
```
|
||||
|
||||
1. Erstelle eine Funktion `endGame()`:
|
||||
|
||||
```javascript
|
||||
function endGame(win) {
|
||||
clearInterval(gameLoopId);
|
||||
|
||||
// set a delay so we are sure any paints have finished
|
||||
setTimeout(() => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
if (win) {
|
||||
displayMessage(
|
||||
"Victory!!! Pew Pew... - Press [Enter] to start a new game Captain Pew Pew",
|
||||
"green"
|
||||
);
|
||||
} else {
|
||||
displayMessage(
|
||||
"You died !!! Press [Enter] to start a new game Captain Pew Pew"
|
||||
);
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
```
|
||||
|
||||
1. **Neustart-Logik**. Wenn alle Leben verloren sind oder der Spieler das Spiel gewonnen hat, zeige an, dass das Spiel neu gestartet werden kann. Starte das Spiel zusätzlich neu, wenn die *Neustart*-Taste gedrückt wird (du kannst entscheiden, welche Taste dem Neustart zugeordnet wird).
|
||||
|
||||
1. Erstelle die Funktion `resetGame()`:
|
||||
|
||||
```javascript
|
||||
function resetGame() {
|
||||
if (gameLoopId) {
|
||||
clearInterval(gameLoopId);
|
||||
eventEmitter.clear();
|
||||
initGame();
|
||||
gameLoopId = setInterval(() => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
drawPoints();
|
||||
drawLife();
|
||||
updateGameObjects();
|
||||
drawGameObjects(ctx);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Füge einen Aufruf zum `eventEmitter` hinzu, um das Spiel in `initGame()` zurückzusetzen:
|
||||
|
||||
```javascript
|
||||
eventEmitter.on(Messages.KEY_EVENT_ENTER, () => {
|
||||
resetGame();
|
||||
});
|
||||
```
|
||||
|
||||
1. Füge dem EventEmitter eine Funktion `clear()` hinzu:
|
||||
|
||||
```javascript
|
||||
clear() {
|
||||
this.listeners = {};
|
||||
}
|
||||
```
|
||||
|
||||
👽 💥 🚀 Glückwunsch, Captain! Dein Spiel ist fertig! Gut gemacht! 🚀 💥 👽
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Füge einen Sound hinzu! Kannst du einen Sound hinzufügen, um dein Spielerlebnis zu verbessern, vielleicht wenn ein Laser trifft, oder der Held stirbt oder gewinnt? Schau dir dieses [Sandbox-Beispiel](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play) an, um zu lernen, wie man mit JavaScript Sound abspielt.
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/40)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Deine Aufgabe ist es, ein neues Beispielspiel zu erstellen. Erkunde einige der interessanten Spiele da draußen, um zu sehen, welche Art von Spiel du bauen könntest.
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Beispielspiel erstellen](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,31 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "24201cf428c7edba1ccec2a78a0dd8f8",
|
||||
"translation_date": "2025-08-24T12:44:20+00:00",
|
||||
"source_file": "6-space-game/6-end-condition/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstelle ein Beispielspiel
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Versuche, ein kleines Spiel zu erstellen, bei dem du verschiedene Endbedingungen übst. Variiere zwischen dem Erreichen einer bestimmten Punktzahl, dem Verlust aller Leben des Helden oder dem Besiegen aller Monster. Baue etwas Einfaches, wie ein textbasiertes Abenteuerspiel in der Konsole. Nutze den untenstehenden Spielablauf als Inspiration:
|
||||
|
||||
```
|
||||
Hero> Strikes with broadsword - orc takes 3p damage
|
||||
Orc> Hits with club - hero takes 2p damage
|
||||
Hero> Kicks - orc takes 1p damage
|
||||
Game> Orc is defeated - Hero collects 2 coins
|
||||
Game> ****No more monsters, you have conquered the evil fortress****
|
||||
```
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ---------------------- | --------------------------- | --------------------------- |
|
||||
| | vollständiges Spiel wird präsentiert | Spiel wird teilweise präsentiert | unvollständiges Spiel enthält Fehler |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:45:21+00:00",
|
||||
"source_file": "6-space-game/6-end-condition/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:44:54+00:00",
|
||||
"source_file": "6-space-game/6-end-condition/your-work/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,43 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "c40a698395ee5102715f7880bba3f2e7",
|
||||
"translation_date": "2025-08-24T12:26:24+00:00",
|
||||
"source_file": "6-space-game/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Baue ein Weltraumspiel
|
||||
|
||||
Ein Weltraumspiel, um fortgeschrittene JavaScript-Grundlagen zu erlernen
|
||||
|
||||
In dieser Lektion lernst du, wie du dein eigenes Weltraumspiel erstellst. Wenn du jemals das Spiel "Space Invaders" gespielt hast, basiert dieses Spiel auf derselben Idee: ein Raumschiff zu steuern und auf Monster zu schießen, die von oben herabkommen. So wird das fertige Spiel aussehen:
|
||||
|
||||

|
||||
|
||||
In diesen sechs Lektionen wirst du Folgendes lernen:
|
||||
|
||||
- **Interagieren** mit dem Canvas-Element, um Dinge auf einem Bildschirm zu zeichnen
|
||||
- **Verstehen** des kartesischen Koordinatensystems
|
||||
- **Erlernen** des Pub-Sub-Musters, um eine solide Spielarchitektur zu schaffen, die einfacher zu warten und zu erweitern ist
|
||||
- **Nutzen** von Async/Await, um Spielressourcen zu laden
|
||||
- **Umgang** mit Tastaturereignissen
|
||||
|
||||
## Überblick
|
||||
|
||||
- Theorie
|
||||
- [Einführung in die Spieleentwicklung mit JavaScript](1-introduction/README.md)
|
||||
- Praxis
|
||||
- [Zeichnen auf Canvas](2-drawing-to-canvas/README.md)
|
||||
- [Elemente auf dem Bildschirm bewegen](3-moving-elements-around/README.md)
|
||||
- [Kollisionserkennung](4-collision-detection/README.md)
|
||||
- [Punkte zählen](5-keeping-score/README.md)
|
||||
- [Spiel beenden und neu starten](6-end-condition/README.md)
|
||||
|
||||
## Credits
|
||||
|
||||
Die verwendeten Assets stammen von https://www.kenney.nl/.
|
||||
Wenn du dich für die Spieleentwicklung interessierst, sind das wirklich großartige Ressourcen. Viele davon sind kostenlos, einige kostenpflichtig.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "068cbb9b3c10a96d503f6cdd6c9ace8c",
|
||||
"translation_date": "2025-08-24T12:45:50+00:00",
|
||||
"source_file": "6-space-game/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
Dies ist ein Platzhalter, absichtlich leer gelassen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,26 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "8223e429218befa731dd5bfd22299520",
|
||||
"translation_date": "2025-08-24T13:41:50+00:00",
|
||||
"source_file": "7-bank-project/1-template-route/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Verbesserung der Routenführung
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Die Routen-Deklaration enthält derzeit nur die Template-ID, die verwendet werden soll. Aber beim Anzeigen einer neuen Seite wird manchmal etwas mehr benötigt. Lassen Sie uns unsere Routing-Implementierung mit zwei zusätzlichen Funktionen verbessern:
|
||||
|
||||
- Geben Sie jedem Template einen Titel und aktualisieren Sie den Fenstertitel mit diesem neuen Titel, wenn sich das Template ändert.
|
||||
- Fügen Sie eine Option hinzu, um nach der Änderung des Templates Code auszuführen. Wir möchten `'Dashboard is shown'` in der Entwicklerkonsole ausgeben, jedes Mal, wenn die Dashboard-Seite angezeigt wird.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
|
||||
| | Die beiden Funktionen sind implementiert und funktionieren. Titel und Codeausführung funktionieren auch für eine neue Route, die in der `routes`-Deklaration hinzugefügt wurde. | Die beiden Funktionen funktionieren, aber das Verhalten ist fest codiert und nicht über die `routes`-Deklaration konfigurierbar. Das Hinzufügen einer dritten Route mit Titel und Codeausführung funktioniert nicht oder nur teilweise. | Eine der Funktionen fehlt oder funktioniert nicht richtig. |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,310 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "b667b7d601e2ee19acb5aa9d102dc9f3",
|
||||
"translation_date": "2025-08-24T13:28:59+00:00",
|
||||
"source_file": "7-bank-project/2-forms/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstellen einer Banking-App Teil 2: Login- und Registrierungsformular erstellen
|
||||
|
||||
## Quiz vor der Lektion
|
||||
|
||||
[Quiz vor der Lektion](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/43)
|
||||
|
||||
### Einführung
|
||||
|
||||
In fast allen modernen Web-Apps können Sie ein Konto erstellen, um Ihren eigenen privaten Bereich zu haben. Da mehrere Benutzer gleichzeitig auf eine Web-App zugreifen können, benötigen Sie einen Mechanismus, um die persönlichen Daten jedes Benutzers separat zu speichern und auszuwählen, welche Informationen angezeigt werden sollen. Wir werden nicht behandeln, wie [Benutzeridentität sicher verwaltet](https://en.wikipedia.org/wiki/Authentication) wird, da dies ein umfangreiches Thema für sich ist, aber wir stellen sicher, dass jeder Benutzer in unserer App ein (oder mehrere) Bankkonten erstellen kann.
|
||||
|
||||
In diesem Teil verwenden wir HTML-Formulare, um Login und Registrierung zu unserer Web-App hinzuzufügen. Wir werden sehen, wie man die Daten programmgesteuert an eine Server-API sendet und schließlich grundlegende Validierungsregeln für Benutzereingaben definiert.
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
Sie müssen die [HTML-Vorlagen und Routing](../1-template-route/README.md) der Web-App für diese Lektion abgeschlossen haben. Außerdem müssen Sie [Node.js](https://nodejs.org) installieren und die [Server-API](../api/README.md) lokal ausführen, damit Sie Daten zum Erstellen von Konten senden können.
|
||||
|
||||
**Beachten Sie**
|
||||
Sie werden zwei Terminals gleichzeitig ausführen, wie unten aufgeführt:
|
||||
1. Für die Haupt-Banking-App, die wir in der Lektion [HTML-Vorlagen und Routing](../1-template-route/README.md) erstellt haben.
|
||||
2. Für die [Bank-App-Server-API](../api/README.md), die wir gerade oben eingerichtet haben.
|
||||
|
||||
Sie benötigen beide Server, die laufen, um den Rest der Lektion zu verfolgen. Sie hören auf verschiedenen Ports (Port `3000` und Port `5000`), sodass alles einwandfrei funktionieren sollte.
|
||||
|
||||
Sie können testen, ob der Server ordnungsgemäß läuft, indem Sie diesen Befehl in einem Terminal ausführen:
|
||||
|
||||
```sh
|
||||
curl http://localhost:5000/api
|
||||
# -> should return "Bank API v1.0.0" as a result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Formular und Steuerelemente
|
||||
|
||||
Das `<form>`-Element kapselt einen Abschnitt eines HTML-Dokuments, in dem der Benutzer Daten mit interaktiven Steuerelementen eingeben und senden kann. Es gibt alle Arten von Benutzeroberflächen-Steuerelementen (UI), die in einem Formular verwendet werden können, das häufigste ist das `<input>`- und das `<button>`-Element.
|
||||
|
||||
Es gibt viele verschiedene [Typen](https://developer.mozilla.org/docs/Web/HTML/Element/input) von `<input>`. Um beispielsweise ein Feld zu erstellen, in das der Benutzer seinen Benutzernamen eingeben kann, können Sie Folgendes verwenden:
|
||||
|
||||
```html
|
||||
<input id="username" name="username" type="text">
|
||||
```
|
||||
|
||||
Das `name`-Attribut wird als Eigenschaftsname verwendet, wenn die Formulardaten gesendet werden. Das `id`-Attribut wird verwendet, um ein `<label>` mit dem Formular-Steuerelement zu verknüpfen.
|
||||
|
||||
> Sehen Sie sich die gesamte Liste der [`<input>`-Typen](https://developer.mozilla.org/docs/Web/HTML/Element/input) und [anderen Formular-Steuerelemente](https://developer.mozilla.org/docs/Learn/Forms/Other_form_controls) an, um eine Vorstellung von allen nativen UI-Elementen zu bekommen, die Sie beim Erstellen Ihrer Benutzeroberfläche verwenden können.
|
||||
|
||||
✅ Beachten Sie, dass `<input>` ein [leeres Element](https://developer.mozilla.org/docs/Glossary/Empty_element) ist, bei dem Sie *keinen* passenden Schließtag hinzufügen sollten. Sie können jedoch die selbstschließende `<input/>`-Notation verwenden, dies ist jedoch nicht erforderlich.
|
||||
|
||||
Das `<button>`-Element innerhalb eines Formulars ist etwas Besonderes. Wenn Sie sein `type`-Attribut nicht angeben, sendet es die Formulardaten automatisch an den Server, wenn es gedrückt wird. Hier sind die möglichen `type`-Werte:
|
||||
|
||||
- `submit`: Standardmäßig innerhalb eines `<form>` löst der Button die Formularübermittlung aus.
|
||||
- `reset`: Der Button setzt alle Formular-Steuerelemente auf ihre ursprünglichen Werte zurück.
|
||||
- `button`: Weist keine Standardaktion zu, wenn der Button gedrückt wird. Sie können dann benutzerdefinierte Aktionen mit JavaScript zuweisen.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Beginnen wir damit, ein Formular zur `login`-Vorlage hinzuzufügen. Wir benötigen ein Feld für den *Benutzernamen* und einen *Login*-Button.
|
||||
|
||||
```html
|
||||
<template id="login">
|
||||
<h1>Bank App</h1>
|
||||
<section>
|
||||
<h2>Login</h2>
|
||||
<form id="loginForm">
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="user" type="text">
|
||||
<button>Login</button>
|
||||
</form>
|
||||
</section>
|
||||
</template>
|
||||
```
|
||||
|
||||
Wenn Sie genauer hinschauen, können Sie feststellen, dass wir hier auch ein `<label>`-Element hinzugefügt haben. `<label>`-Elemente werden verwendet, um einem UI-Steuerelement wie unserem Benutzernamenfeld einen Namen zu geben. Labels sind wichtig für die Lesbarkeit Ihrer Formulare, bieten aber auch zusätzliche Vorteile:
|
||||
|
||||
- Durch die Verknüpfung eines Labels mit einem Formular-Steuerelement wird Benutzern, die unterstützende Technologien verwenden (wie ein Screenreader), geholfen zu verstehen, welche Daten sie eingeben sollen.
|
||||
- Sie können auf das Label klicken, um direkt den Fokus auf das zugehörige Eingabefeld zu setzen, was die Bedienung auf Touchscreen-Geräten erleichtert.
|
||||
|
||||
> [Barrierefreiheit](https://developer.mozilla.org/docs/Learn/Accessibility/What_is_accessibility) im Web ist ein sehr wichtiges Thema, das oft übersehen wird. Dank [semantischer HTML-Elemente](https://developer.mozilla.org/docs/Learn/Accessibility/HTML) ist es nicht schwierig, barrierefreie Inhalte zu erstellen, wenn Sie sie richtig verwenden. Sie können [mehr über Barrierefreiheit lesen](https://developer.mozilla.org/docs/Web/Accessibility), um häufige Fehler zu vermeiden und ein verantwortungsbewusster Entwickler zu werden.
|
||||
|
||||
Nun fügen wir ein zweites Formular für die Registrierung direkt unter dem vorherigen hinzu:
|
||||
|
||||
```html
|
||||
<hr/>
|
||||
<h2>Register</h2>
|
||||
<form id="registerForm">
|
||||
<label for="user">Username</label>
|
||||
<input id="user" name="user" type="text">
|
||||
<label for="currency">Currency</label>
|
||||
<input id="currency" name="currency" type="text" value="$">
|
||||
<label for="description">Description</label>
|
||||
<input id="description" name="description" type="text">
|
||||
<label for="balance">Current balance</label>
|
||||
<input id="balance" name="balance" type="number" value="0">
|
||||
<button>Register</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
Mit dem `value`-Attribut können wir einen Standardwert für eine bestimmte Eingabe definieren. Beachten Sie auch, dass das Eingabefeld für `balance` den Typ `number` hat. Sieht es anders aus als die anderen Eingaben? Versuchen Sie, damit zu interagieren.
|
||||
|
||||
✅ Können Sie die Formulare nur mit einer Tastatur navigieren und bedienen? Wie würden Sie das tun?
|
||||
|
||||
## Daten an den Server senden
|
||||
|
||||
Jetzt, da wir eine funktionale Benutzeroberfläche haben, ist der nächste Schritt, die Daten an unseren Server zu senden. Machen wir einen kurzen Test mit unserem aktuellen Code: Was passiert, wenn Sie auf den *Login*- oder *Register*-Button klicken?
|
||||
|
||||
Haben Sie die Änderung im URL-Bereich Ihres Browsers bemerkt?
|
||||
|
||||

|
||||
|
||||
Die Standardaktion für ein `<form>` ist, das Formular an die aktuelle Server-URL mit der [GET-Methode](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3) zu senden, wobei die Formulardaten direkt an die URL angehängt werden. Diese Methode hat jedoch einige Nachteile:
|
||||
|
||||
- Die gesendeten Daten sind in der Größe begrenzt (etwa 2000 Zeichen).
|
||||
- Die Daten sind direkt in der URL sichtbar (nicht ideal für Passwörter).
|
||||
- Sie funktioniert nicht mit Datei-Uploads.
|
||||
|
||||
Deshalb können Sie sie ändern, um die [POST-Methode](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) zu verwenden, die die Formulardaten im Body der HTTP-Anfrage an den Server sendet, ohne die vorherigen Einschränkungen.
|
||||
|
||||
> Während POST die am häufigsten verwendete Methode zum Senden von Daten ist, [gibt es in einigen spezifischen Szenarien](https://www.w3.org/2001/tag/doc/whenToUseGet.html) Fälle, in denen es vorzuziehen ist, die GET-Methode zu verwenden, beispielsweise bei der Implementierung eines Suchfelds.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Fügen Sie der Registrierungsformular die Eigenschaften `action` und `method` hinzu:
|
||||
|
||||
```html
|
||||
<form id="registerForm" action="//localhost:5000/api/accounts" method="POST">
|
||||
```
|
||||
|
||||
Versuchen Sie nun, ein neues Konto mit Ihrem Namen zu registrieren. Nachdem Sie auf den *Register*-Button geklickt haben, sollten Sie etwas wie das Folgende sehen:
|
||||
|
||||

|
||||
|
||||
Wenn alles gut läuft, sollte der Server Ihre Anfrage mit einer [JSON](https://www.json.org/json-en.html)-Antwort beantworten, die die erstellten Kontodaten enthält.
|
||||
|
||||
✅ Versuchen Sie erneut, sich mit demselben Namen zu registrieren. Was passiert?
|
||||
|
||||
## Daten senden, ohne die Seite neu zu laden
|
||||
|
||||
Wie Sie wahrscheinlich bemerkt haben, gibt es ein kleines Problem mit dem Ansatz, den wir gerade verwendet haben: Beim Absenden des Formulars verlassen wir unsere App und der Browser leitet zur Server-URL weiter. Wir versuchen, alle Seitenneuladungen mit unserer Web-App zu vermeiden, da wir eine [Single-Page-Anwendung (SPA)](https://en.wikipedia.org/wiki/Single-page_application) erstellen.
|
||||
|
||||
Um die Formulardaten an den Server zu senden, ohne eine Seitenneuladung zu erzwingen, müssen wir JavaScript-Code verwenden. Anstatt eine URL in die `action`-Eigenschaft eines `<form>`-Elements zu setzen, können Sie beliebigen JavaScript-Code mit dem Präfix `javascript:` verwenden, um eine benutzerdefinierte Aktion auszuführen. Dies bedeutet auch, dass Sie einige Aufgaben implementieren müssen, die zuvor automatisch vom Browser ausgeführt wurden:
|
||||
|
||||
- Die Formulardaten abrufen.
|
||||
- Die Formulardaten in ein geeignetes Format konvertieren und codieren.
|
||||
- Die HTTP-Anfrage erstellen und an den Server senden.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Ersetzen Sie die `action` des Registrierungsformulars durch:
|
||||
|
||||
```html
|
||||
<form id="registerForm" action="javascript:register()">
|
||||
```
|
||||
|
||||
Öffnen Sie `app.js` und fügen Sie eine neue Funktion namens `register` hinzu:
|
||||
|
||||
```js
|
||||
function register() {
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
const formData = new FormData(registerForm);
|
||||
const data = Object.fromEntries(formData);
|
||||
const jsonData = JSON.stringify(data);
|
||||
}
|
||||
```
|
||||
|
||||
Hier rufen wir das Formularelement mit `getElementById()` ab und verwenden den [`FormData`](https://developer.mozilla.org/docs/Web/API/FormData)-Helfer, um die Werte aus den Formular-Steuerelementen als Satz von Schlüssel/Wert-Paaren zu extrahieren. Dann konvertieren wir die Daten in ein reguläres Objekt mit [`Object.fromEntries()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries) und serialisieren die Daten schließlich in [JSON](https://www.json.org/json-en.html), ein Format, das häufig für den Datenaustausch im Web verwendet wird.
|
||||
|
||||
Die Daten sind jetzt bereit, an den Server gesendet zu werden. Erstellen Sie eine neue Funktion namens `createAccount`:
|
||||
|
||||
```js
|
||||
async function createAccount(account) {
|
||||
try {
|
||||
const response = await fetch('//localhost:5000/api/accounts', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: account
|
||||
});
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
return { error: error.message || 'Unknown error' };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Was macht diese Funktion? Beachten Sie zuerst das `async`-Schlüsselwort hier. Dies bedeutet, dass die Funktion Code enthält, der [**asynchron**](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) ausgeführt wird. Wenn es zusammen mit dem `await`-Schlüsselwort verwendet wird, ermöglicht es das Warten auf die Ausführung von asynchronem Code - wie das Warten auf die Serverantwort hier - bevor es weitergeht.
|
||||
|
||||
Hier ist ein kurzes Video über die Verwendung von `async/await`:
|
||||
|
||||
[](https://youtube.com/watch?v=YwmlRkrxvkk "Async und Await für die Verwaltung von Promises")
|
||||
|
||||
> 🎥 Klicken Sie auf das Bild oben für ein Video über async/await.
|
||||
|
||||
Wir verwenden die `fetch()`-API, um JSON-Daten an den Server zu senden. Diese Methode benötigt 2 Parameter:
|
||||
|
||||
- Die URL des Servers, daher setzen wir hier wieder `//localhost:5000/api/accounts`.
|
||||
- Die Einstellungen der Anfrage. Hier setzen wir die Methode auf `POST` und stellen den `body` für die Anfrage bereit. Da wir JSON-Daten an den Server senden, müssen wir auch den `Content-Type`-Header auf `application/json` setzen, damit der Server weiß, wie er den Inhalt interpretieren soll.
|
||||
|
||||
Da der Server die Anfrage mit JSON beantwortet, können wir `await response.json()` verwenden, um den JSON-Inhalt zu analysieren und das resultierende Objekt zurückzugeben. Beachten Sie, dass diese Methode asynchron ist, daher verwenden wir hier das `await`-Schlüsselwort, bevor wir zurückkehren, um sicherzustellen, dass alle Fehler während der Analyse ebenfalls abgefangen werden.
|
||||
|
||||
Fügen Sie nun etwas Code zur `register`-Funktion hinzu, um `createAccount()` aufzurufen:
|
||||
|
||||
```js
|
||||
const result = await createAccount(jsonData);
|
||||
```
|
||||
|
||||
Da wir hier das `await`-Schlüsselwort verwenden, müssen wir das `async`-Schlüsselwort vor der `register`-Funktion hinzufügen:
|
||||
|
||||
```js
|
||||
async function register() {
|
||||
```
|
||||
|
||||
Fügen Sie schließlich einige Logs hinzu, um das Ergebnis zu überprüfen. Die endgültige Funktion sollte wie folgt aussehen:
|
||||
|
||||
```js
|
||||
async function register() {
|
||||
const registerForm = document.getElementById('registerForm');
|
||||
const formData = new FormData(registerForm);
|
||||
const jsonData = JSON.stringify(Object.fromEntries(formData));
|
||||
const result = await createAccount(jsonData);
|
||||
|
||||
if (result.error) {
|
||||
return console.log('An error occurred:', result.error);
|
||||
}
|
||||
|
||||
console.log('Account created!', result);
|
||||
}
|
||||
```
|
||||
|
||||
Das war ein bisschen lang, aber wir haben es geschafft! Wenn Sie Ihre [Entwicklerwerkzeuge des Browsers](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools) öffnen und versuchen, ein neues Konto zu registrieren, sollten Sie keine Änderung auf der Webseite sehen, aber eine Nachricht wird in der Konsole angezeigt, die bestätigt, dass alles funktioniert.
|
||||
|
||||

|
||||
|
||||
✅ Denken Sie, dass die Daten sicher an den Server gesendet werden? Was wäre, wenn jemand die Anfrage abfangen könnte? Sie können über [HTTPS](https://en.wikipedia.org/wiki/HTTPS) lesen, um mehr über sichere Datenkommunikation zu erfahren.
|
||||
|
||||
## Datenvalidierung
|
||||
|
||||
Wenn Sie versuchen, ein neues Konto zu registrieren, ohne zuerst einen Benutzernamen festzulegen, können Sie sehen, dass der Server einen Fehler mit dem Statuscode [400 (Bad Request)](https://developer.mozilla.org/docs/Web/HTTP/Status/400#:~:text=The%20HyperText%20Transfer%20Protocol%20(HTTP,%2C%20or%20deceptive%20request%20routing).) zurückgibt.
|
||||
|
||||
Bevor Daten an einen Server gesendet werden, ist es eine gute Praxis, [die Formulardaten zu validieren](https://developer.mozilla.org/docs/Learn/Forms/Form_validation), wenn möglich, um sicherzustellen, dass Sie eine gültige Anfrage senden. HTML5-Formular-Steuerelemente bieten integrierte Validierung mithilfe verschiedener Attribute:
|
||||
|
||||
- `required`: Das Feld muss ausgefüllt werden, sonst kann das Formular nicht gesendet werden.
|
||||
- `minlength` und `maxlength`: Definiert die minimale und maximale Anzahl von Zeichen in Textfeldern.
|
||||
- `min` und `max`: Definiert den minimalen und maximalen Wert eines numerischen Feldes.
|
||||
- `type`: Definiert die Art der erwarteten Daten, wie `number`, `email`, `file` oder [andere integrierte Typen](https://developer.mozilla.org/docs/Web/HTML/Element/input). Dieses Attribut kann auch die visuelle Darstellung des Formular-Steuerelements ändern.
|
||||
- `pattern`: Ermöglicht die Definition eines [regulären Ausdrucks](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Regular_Expressions), um zu testen, ob die eingegebenen Daten gültig sind oder nicht.
|
||||
Tipp: Sie können das Erscheinungsbild Ihrer Formularsteuerelemente anpassen, je nachdem, ob sie gültig oder ungültig sind, indem Sie die CSS-Pseudoklassen `:valid` und `:invalid` verwenden.
|
||||
### Aufgabe
|
||||
|
||||
Es gibt zwei Pflichtfelder, um ein gültiges neues Konto zu erstellen: den Benutzernamen und die Währung. Die anderen Felder sind optional. Aktualisieren Sie das HTML-Formular, indem Sie sowohl das `required`-Attribut als auch den Text im Feldlabel verwenden, sodass:
|
||||
|
||||
```html
|
||||
<label for="user">Username (required)</label>
|
||||
<input id="user" name="user" type="text" required>
|
||||
...
|
||||
<label for="currency">Currency (required)</label>
|
||||
<input id="currency" name="currency" type="text" value="$" required>
|
||||
```
|
||||
|
||||
Obwohl diese spezielle Serverimplementierung keine spezifischen Begrenzungen für die maximale Länge der Felder erzwingt, ist es immer eine gute Praxis, vernünftige Grenzen für jede Benutzereingabe zu definieren.
|
||||
|
||||
Fügen Sie ein `maxlength`-Attribut zu den Textfeldern hinzu:
|
||||
|
||||
```html
|
||||
<input id="user" name="user" type="text" maxlength="20" required>
|
||||
...
|
||||
<input id="currency" name="currency" type="text" value="$" maxlength="5" required>
|
||||
...
|
||||
<input id="description" name="description" type="text" maxlength="100">
|
||||
```
|
||||
|
||||
Wenn Sie nun die *Registrieren*-Schaltfläche drücken und ein Feld nicht einer der von uns definierten Validierungsregeln entspricht, sollten Sie etwas wie das Folgende sehen:
|
||||
|
||||

|
||||
|
||||
Eine solche Validierung, die *vor* dem Senden von Daten an den Server durchgeführt wird, wird als **Client-seitige** Validierung bezeichnet. Beachten Sie jedoch, dass es nicht immer möglich ist, alle Prüfungen ohne das Senden der Daten durchzuführen. Zum Beispiel können wir hier nicht überprüfen, ob ein Konto mit demselben Benutzernamen bereits existiert, ohne eine Anfrage an den Server zu senden. Zusätzliche Validierungen, die auf dem Server durchgeführt werden, werden als **Server-seitige** Validierung bezeichnet.
|
||||
|
||||
In der Regel müssen beide implementiert werden. Während die Client-seitige Validierung die Benutzererfahrung verbessert, indem sie dem Benutzer sofortiges Feedback gibt, ist die Server-seitige Validierung entscheidend, um sicherzustellen, dass die Benutzerdaten, die Sie verarbeiten, korrekt und sicher sind.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Zeigen Sie eine Fehlermeldung im HTML an, wenn der Benutzer bereits existiert.
|
||||
|
||||
Hier ist ein Beispiel, wie die endgültige Login-Seite nach ein wenig Styling aussehen könnte:
|
||||
|
||||

|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/44)
|
||||
|
||||
## Überprüfung & Selbststudium
|
||||
|
||||
Entwickler sind sehr kreativ geworden, wenn es um ihre Bemühungen beim Erstellen von Formularen geht, insbesondere in Bezug auf Validierungsstrategien. Informieren Sie sich über verschiedene Formularabläufe, indem Sie [CodePen](https://codepen.com) durchstöbern. Können Sie interessante und inspirierende Formulare finden?
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Stylen Sie Ihre Bank-App](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "474f3ab1ee755ca980fc9104a0316e17",
|
||||
"translation_date": "2025-08-24T13:32:31+00:00",
|
||||
"source_file": "7-bank-project/2-forms/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Gestalte deine Bank-App
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Erstelle eine neue Datei `styles.css` und füge einen Link dazu in deine aktuelle Datei `index.html` ein. Füge in der gerade erstellten CSS-Datei einige Styles hinzu, um die *Login*- und *Dashboard*-Seite ansprechend und ordentlich zu gestalten. Versuche, ein Farbschema zu erstellen, um deiner App eine eigene Markenidentität zu verleihen.
|
||||
|
||||
> Tipp: Du kannst das HTML bearbeiten und neue Elemente und Klassen hinzufügen, falls nötig.
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| | Alle Seiten sehen sauber und gut lesbar aus, mit einem konsistenten Farbschema und klar hervorgehobenen Abschnitten. | Seiten sind gestaltet, aber ohne einheitliches Thema oder mit unscharf abgegrenzten Abschnitten. | Seiten fehlen Styling, die Abschnitte wirken unorganisiert und die Informationen sind schwer lesbar. |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,345 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "f587e913e3f7c0b1c549a05dd74ee8e5",
|
||||
"translation_date": "2025-08-24T13:34:07+00:00",
|
||||
"source_file": "7-bank-project/3-data/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstellen einer Banking-App Teil 3: Methoden zum Abrufen und Verwenden von Daten
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/45)
|
||||
|
||||
### Einführung
|
||||
|
||||
Im Kern jeder Webanwendung stehen *Daten*. Daten können viele Formen annehmen, aber ihr Hauptzweck ist es immer, dem Benutzer Informationen anzuzeigen. Da Webanwendungen zunehmend interaktiver und komplexer werden, ist die Art und Weise, wie der Benutzer auf Informationen zugreift und mit ihnen interagiert, ein zentraler Bestandteil der Webentwicklung.
|
||||
|
||||
In dieser Lektion werden wir sehen, wie man Daten asynchron von einem Server abruft und diese Daten verwendet, um Informationen auf einer Webseite anzuzeigen, ohne das HTML neu zu laden.
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
Für diese Lektion musst du den [Login- und Registrierungsformular](../2-forms/README.md)-Teil der Webanwendung erstellt haben. Außerdem musst du [Node.js](https://nodejs.org) installieren und die [Server-API](../api/README.md) lokal ausführen, um auf Kontodaten zuzugreifen.
|
||||
|
||||
Du kannst testen, ob der Server ordnungsgemäß läuft, indem du diesen Befehl in einem Terminal ausführst:
|
||||
|
||||
```sh
|
||||
curl http://localhost:5000/api
|
||||
# -> should return "Bank API v1.0.0" as a result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AJAX und Datenabruf
|
||||
|
||||
Traditionelle Webseiten aktualisieren den angezeigten Inhalt, wenn der Benutzer einen Link auswählt oder Daten über ein Formular sendet, indem die gesamte HTML-Seite neu geladen wird. Jedes Mal, wenn neue Daten geladen werden müssen, liefert der Webserver eine komplett neue HTML-Seite, die vom Browser verarbeitet werden muss. Dies unterbricht die aktuelle Benutzeraktion und schränkt die Interaktionen während des Neuladens ein. Dieser Workflow wird auch als *Multi-Page Application* oder *MPA* bezeichnet.
|
||||
|
||||

|
||||
|
||||
Als Webanwendungen komplexer und interaktiver wurden, entstand eine neue Technik namens [AJAX (Asynchronous JavaScript and XML)](https://de.wikipedia.org/wiki/Ajax_(Programmierung)). Diese Technik ermöglicht es Webanwendungen, Daten asynchron von einem Server zu senden und abzurufen, ohne die HTML-Seite neu laden zu müssen. Das führt zu schnelleren Updates und flüssigeren Benutzerinteraktionen. Wenn neue Daten vom Server empfangen werden, kann die aktuelle HTML-Seite auch mit JavaScript über die [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)-API aktualisiert werden. Im Laufe der Zeit hat sich dieser Ansatz zu dem entwickelt, was heute als [*Single-Page Application* oder *SPA*](https://de.wikipedia.org/wiki/Single-Page-Webanwendung) bekannt ist.
|
||||
|
||||

|
||||
|
||||
Als AJAX erstmals eingeführt wurde, war die einzige verfügbare API zum asynchronen Abrufen von Daten [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Moderne Browser implementieren jedoch auch die bequemere und leistungsfähigere [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), die auf Promises basiert und besser geeignet ist, um JSON-Daten zu verarbeiten.
|
||||
|
||||
> Obwohl alle modernen Browser die `Fetch API` unterstützen, solltest du, wenn deine Webanwendung auch auf älteren Browsern funktionieren soll, immer die [Kompatibilitätstabelle auf caniuse.com](https://caniuse.com/fetch) überprüfen.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
In [der vorherigen Lektion](../2-forms/README.md) haben wir das Registrierungsformular implementiert, um ein Konto zu erstellen. Jetzt fügen wir Code hinzu, um sich mit einem bestehenden Konto anzumelden und dessen Daten abzurufen. Öffne die Datei `app.js` und füge eine neue Funktion `login` hinzu:
|
||||
|
||||
```js
|
||||
async function login() {
|
||||
const loginForm = document.getElementById('loginForm')
|
||||
const user = loginForm.user.value;
|
||||
}
|
||||
```
|
||||
|
||||
Hier beginnen wir damit, das Formularelement mit `getElementById()` abzurufen, und holen dann den Benutzernamen aus dem Eingabefeld mit `loginForm.user.value`. Jedes Formularelement kann über seinen Namen (im HTML mit dem Attribut `name` festgelegt) als Eigenschaft des Formulars aufgerufen werden.
|
||||
|
||||
Ähnlich wie bei der Registrierung erstellen wir eine weitere Funktion, um eine Serveranfrage auszuführen, diesmal jedoch, um die Kontodaten abzurufen:
|
||||
|
||||
```js
|
||||
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' };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wir verwenden die `fetch` API, um die Daten asynchron vom Server anzufordern. Diesmal benötigen wir keine zusätzlichen Parameter außer der URL, da wir nur Daten abfragen. Standardmäßig erstellt `fetch` eine [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET)-HTTP-Anfrage, was hier genau das ist, was wir brauchen.
|
||||
|
||||
✅ `encodeURIComponent()` ist eine Funktion, die Sonderzeichen für URLs maskiert. Welche Probleme könnten auftreten, wenn wir diese Funktion nicht aufrufen und den Wert von `user` direkt in der URL verwenden?
|
||||
|
||||
Jetzt aktualisieren wir unsere `login`-Funktion, um `getAccount` zu verwenden:
|
||||
|
||||
```js
|
||||
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');
|
||||
}
|
||||
```
|
||||
|
||||
Da `getAccount` eine asynchrone Funktion ist, müssen wir sie mit dem Schlüsselwort `await` verwenden, um auf das Serverergebnis zu warten. Wie bei jeder Serveranfrage müssen wir auch Fehlerfälle behandeln. Für den Moment fügen wir nur eine Log-Nachricht hinzu, um den Fehler anzuzeigen, und kommen später darauf zurück.
|
||||
|
||||
Dann müssen wir die Daten irgendwo speichern, damit wir sie später verwenden können, um die Dashboard-Informationen anzuzeigen. Da die Variable `account` noch nicht existiert, erstellen wir eine globale Variable dafür am Anfang unserer Datei:
|
||||
|
||||
```js
|
||||
let account = null;
|
||||
```
|
||||
|
||||
Nachdem die Benutzerdaten in einer Variablen gespeichert wurden, können wir mit der Funktion `navigate()` von der *Login*-Seite zum *Dashboard* wechseln.
|
||||
|
||||
Schließlich müssen wir unsere `login`-Funktion aufrufen, wenn das Login-Formular abgeschickt wird, indem wir das HTML ändern:
|
||||
|
||||
```html
|
||||
<form id="loginForm" action="javascript:login()">
|
||||
```
|
||||
|
||||
Teste, ob alles korrekt funktioniert, indem du ein neues Konto registrierst und versuchst, dich mit demselben Konto anzumelden.
|
||||
|
||||
Bevor wir zum nächsten Teil übergehen, können wir auch die `register`-Funktion vervollständigen, indem wir dies am Ende der Funktion hinzufügen:
|
||||
|
||||
```js
|
||||
account = result;
|
||||
navigate('/dashboard');
|
||||
```
|
||||
|
||||
✅ Wusstest du, dass du standardmäßig nur Server-APIs von derselben *Domain und Port* wie die Webseite, die du ansiehst, aufrufen kannst? Dies ist ein Sicherheitsmechanismus, der von Browsern durchgesetzt wird. Aber Moment mal, unsere Web-App läuft auf `localhost:3000`, während die Server-API auf `localhost:5000` läuft. Warum funktioniert das? Durch die Verwendung einer Technik namens [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/docs/Web/HTTP/CORS) ist es möglich, Cross-Origin-HTTP-Anfragen auszuführen, wenn der Server spezielle Header zur Antwort hinzufügt, die Ausnahmen für bestimmte Domains erlauben.
|
||||
|
||||
> Erfahre mehr über APIs in dieser [Lektion](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon)
|
||||
|
||||
## HTML aktualisieren, um Daten anzuzeigen
|
||||
|
||||
Jetzt, da wir die Benutzerdaten haben, müssen wir das bestehende HTML aktualisieren, um sie anzuzeigen. Wir wissen bereits, wie man ein Element aus dem DOM abruft, z. B. mit `document.getElementById()`. Nachdem du ein Basiselement hast, kannst du mit diesen APIs den Inhalt ändern oder Kind-Elemente hinzufügen:
|
||||
|
||||
- Mit der [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent)-Eigenschaft kannst du den Text eines Elements ändern. Beachte, dass das Ändern dieses Werts alle Kind-Elemente des Elements (falls vorhanden) entfernt und durch den angegebenen Text ersetzt. Daher ist es auch eine effiziente Methode, alle Kinder eines Elements zu entfernen, indem man ihm einen leeren String `''` zuweist.
|
||||
|
||||
- Mit [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) und der [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append)-Methode kannst du ein oder mehrere neue Kind-Elemente erstellen und anhängen.
|
||||
|
||||
✅ Mit der [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML)-Eigenschaft eines Elements ist es ebenfalls möglich, dessen HTML-Inhalt zu ändern. Diese Methode sollte jedoch vermieden werden, da sie anfällig für [Cross-Site-Scripting (XSS)](https://developer.mozilla.org/docs/Glossary/Cross-site_scripting)-Angriffe ist.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Bevor wir zur Dashboard-Seite übergehen, sollten wir noch etwas auf der *Login*-Seite erledigen. Derzeit wird, wenn du versuchst, dich mit einem nicht existierenden Benutzernamen anzumelden, eine Nachricht in der Konsole angezeigt, aber für einen normalen Benutzer ändert sich nichts, und man weiß nicht, was los ist.
|
||||
|
||||
Fügen wir ein Platzhalterelement im Login-Formular hinzu, in dem wir bei Bedarf eine Fehlermeldung anzeigen können. Ein guter Platz wäre direkt vor dem Login-`<button>`:
|
||||
|
||||
```html
|
||||
...
|
||||
<div id="loginError"></div>
|
||||
<button>Login</button>
|
||||
...
|
||||
```
|
||||
|
||||
Dieses `<div>`-Element ist leer, was bedeutet, dass nichts auf dem Bildschirm angezeigt wird, bis wir ihm Inhalte hinzufügen. Wir geben ihm auch eine `id`, damit wir es leicht mit JavaScript abrufen können.
|
||||
|
||||
Gehe zurück zur Datei `app.js` und erstelle eine neue Hilfsfunktion `updateElement`:
|
||||
|
||||
```js
|
||||
function updateElement(id, text) {
|
||||
const element = document.getElementById(id);
|
||||
element.textContent = text;
|
||||
}
|
||||
```
|
||||
|
||||
Diese Funktion ist ziemlich einfach: Sie aktualisiert den Textinhalt des DOM-Elements mit der passenden `id`, basierend auf den übergebenen Parametern *id* und *text*. Verwenden wir diese Methode anstelle der vorherigen Fehlermeldung in der `login`-Funktion:
|
||||
|
||||
```js
|
||||
if (data.error) {
|
||||
return updateElement('loginError', data.error);
|
||||
}
|
||||
```
|
||||
|
||||
Wenn du jetzt versuchst, dich mit einem ungültigen Konto anzumelden, solltest du etwas wie das Folgende sehen:
|
||||
|
||||

|
||||
|
||||
Jetzt haben wir einen Fehlertext, der visuell angezeigt wird. Wenn du jedoch einen Screenreader verwendest, wirst du feststellen, dass nichts angesagt wird. Damit Text, der dynamisch zu einer Seite hinzugefügt wird, von Screenreadern angesagt wird, muss er eine sogenannte [Live Region](https://developer.mozilla.org/docs/Web/Accessibility/ARIA/ARIA_Live_Regions) verwenden. Hier verwenden wir eine spezielle Art von Live-Region, die als Alert bezeichnet wird:
|
||||
|
||||
```html
|
||||
<div id="loginError" role="alert"></div>
|
||||
```
|
||||
|
||||
Implementiere das gleiche Verhalten für die Fehler in der `register`-Funktion (vergiss nicht, das HTML zu aktualisieren).
|
||||
|
||||
## Informationen im Dashboard anzeigen
|
||||
|
||||
Mit den gleichen Techniken, die wir gerade gesehen haben, kümmern wir uns auch um die Anzeige der Kontoinformationen auf der Dashboard-Seite.
|
||||
|
||||
So sieht ein vom Server empfangenes Kontoobjekt aus:
|
||||
|
||||
```json
|
||||
{
|
||||
"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 }
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
> Hinweis: Um dir das Leben zu erleichtern, kannst du das vorgefertigte `test`-Konto verwenden, das bereits mit Daten gefüllt ist.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Beginnen wir damit, den Abschnitt "Balance" im HTML zu ersetzen, um Platzhalterelemente hinzuzufügen:
|
||||
|
||||
```html
|
||||
<section>
|
||||
Balance: <span id="balance"></span><span id="currency"></span>
|
||||
</section>
|
||||
```
|
||||
|
||||
Wir fügen auch einen neuen Abschnitt direkt darunter hinzu, um die Kontobeschreibung anzuzeigen:
|
||||
|
||||
```html
|
||||
<h2 id="description"></h2>
|
||||
```
|
||||
|
||||
✅ Da die Kontobeschreibung als Titel für den darunter liegenden Inhalt fungiert, wird sie semantisch als Überschrift ausgezeichnet. Erfahre mehr darüber, wie [Überschriftenstruktur](https://www.nomensa.com/blog/2017/how-structure-headings-web-accessibility) für die Barrierefreiheit wichtig ist, und wirf einen kritischen Blick auf die Seite, um zu bestimmen, was sonst noch eine Überschrift sein könnte.
|
||||
|
||||
Als Nächstes erstellen wir eine neue Funktion in `app.js`, um die Platzhalter zu füllen:
|
||||
|
||||
```js
|
||||
function updateDashboard() {
|
||||
if (!account) {
|
||||
return navigate('/login');
|
||||
}
|
||||
|
||||
updateElement('description', account.description);
|
||||
updateElement('balance', account.balance.toFixed(2));
|
||||
updateElement('currency', account.currency);
|
||||
}
|
||||
```
|
||||
|
||||
Zuerst überprüfen wir, ob wir die benötigten Kontodaten haben, bevor wir fortfahren. Dann verwenden wir die zuvor erstellte Funktion `updateElement()`, um das HTML zu aktualisieren.
|
||||
|
||||
> Um die Anzeige des Kontostands ansprechender zu gestalten, verwenden wir die Methode [`toFixed(2)`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed), um den Wert mit 2 Nachkommastellen anzuzeigen.
|
||||
|
||||
Jetzt müssen wir unsere `updateDashboard()`-Funktion jedes Mal aufrufen, wenn das Dashboard geladen wird. Wenn du die [Aufgabe aus Lektion 1](../1-template-route/assignment.md) bereits abgeschlossen hast, sollte dies einfach sein. Andernfalls kannst du die folgende Implementierung verwenden.
|
||||
|
||||
Füge diesen Code am Ende der Funktion `updateRoute()` hinzu:
|
||||
|
||||
```js
|
||||
if (typeof route.init === 'function') {
|
||||
route.init();
|
||||
}
|
||||
```
|
||||
|
||||
Und aktualisiere die Routen-Definition mit:
|
||||
|
||||
```js
|
||||
const routes = {
|
||||
'/login': { templateId: 'login' },
|
||||
'/dashboard': { templateId: 'dashboard', init: updateDashboard }
|
||||
};
|
||||
```
|
||||
|
||||
Mit dieser Änderung wird die Funktion `updateDashboard()` jedes Mal aufgerufen, wenn die Dashboard-Seite angezeigt wird. Nach einem Login solltest du dann den Kontostand, die Währung und die Beschreibung sehen können.
|
||||
|
||||
## Tabellenzeilen dynamisch mit HTML-Templates erstellen
|
||||
|
||||
In der [ersten Lektion](../1-template-route/README.md) haben wir HTML-Templates zusammen mit der Methode [`appendChild()`](https://developer.mozilla.org/docs/Web/API/Node/appendChild) verwendet, um die Navigation in unserer App zu implementieren. Templates können auch kleiner sein und verwendet werden, um sich wiederholende Teile einer Seite dynamisch zu füllen.
|
||||
|
||||
Wir verwenden einen ähnlichen Ansatz, um die Liste der Transaktionen in der HTML-Tabelle anzuzeigen.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Füge ein neues Template in den HTML-`<body>`-Bereich ein:
|
||||
|
||||
```html
|
||||
<template id="transaction">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</template>
|
||||
```
|
||||
|
||||
Dieses Template stellt eine einzelne Tabellenzeile dar, mit den 3 Spalten, die wir füllen möchten: *Datum*, *Objekt* und *Betrag* einer Transaktion.
|
||||
|
||||
Füge dann diese `id`-Eigenschaft zum `<tbody>`-Element der Tabelle im Dashboard-Template hinzu, um es mit JavaScript leichter zu finden:
|
||||
|
||||
```html
|
||||
<tbody id="transactions"></tbody>
|
||||
```
|
||||
|
||||
Unser HTML ist bereit. Wechseln wir zum JavaScript-Code und erstellen eine neue Funktion `createTransactionRow`:
|
||||
|
||||
```js
|
||||
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;
|
||||
}
|
||||
```
|
||||
|
||||
Diese Funktion macht genau das, was ihr Name andeutet: Sie verwendet das zuvor erstellte Template, um eine neue Tabellenzeile zu erstellen und deren Inhalte mit Transaktionsdaten zu füllen. Wir verwenden dies in unserer `updateDashboard()`-Funktion, um die Tabelle zu füllen:
|
||||
|
||||
```js
|
||||
const transactionsRows = document.createDocumentFragment();
|
||||
for (const transaction of account.transactions) {
|
||||
const transactionRow = createTransactionRow(transaction);
|
||||
transactionsRows.appendChild(transactionRow);
|
||||
}
|
||||
updateElement('transactions', transactionsRows);
|
||||
```
|
||||
|
||||
Hier verwenden wir die Methode [`document.createDocumentFragment()`](https://developer.mozilla.org/docs/Web/API/Document/createDocumentFragment), die ein neues DOM-Fragment erstellt, mit dem wir arbeiten können, bevor wir es schließlich an unsere HTML-Tabelle anhängen.
|
||||
|
||||
Es gibt noch eine Sache, die wir tun müssen, bevor dieser Code funktioniert, da unsere Funktion `updateElement()` derzeit nur Textinhalte unterstützt. Ändern wir ihren Code ein wenig:
|
||||
|
||||
```js
|
||||
function updateElement(id, textOrNode) {
|
||||
const element = document.getElementById(id);
|
||||
element.textContent = ''; // Removes all children
|
||||
element.append(textOrNode);
|
||||
}
|
||||
```
|
||||
|
||||
Wir verwenden die Methode [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append), da sie es ermöglicht, entweder Text oder [DOM-Knoten](https://developer.mozilla.org/docs/Web/API/Node) an ein übergeordnetes Element anzuhängen, was perfekt für all unsere Anwendungsfälle ist.
|
||||
Wenn Sie versuchen, sich mit dem `test`-Konto anzumelden, sollten Sie jetzt eine Transaktionsliste auf dem Dashboard sehen 🎉.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Arbeitet zusammen, um die Dashboard-Seite wie eine echte Banking-App aussehen zu lassen. Falls ihr eure App bereits gestaltet habt, versucht [Media Queries](https://developer.mozilla.org/docs/Web/CSS/Media_Queries) zu verwenden, um ein [responsives Design](https://developer.mozilla.org/docs/Web/Progressive_web_apps/Responsive/responsive_design_building_blocks) zu erstellen, das sowohl auf Desktop- als auch auf Mobilgeräten gut funktioniert.
|
||||
|
||||
Hier ist ein Beispiel für eine gestaltete Dashboard-Seite:
|
||||
|
||||

|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/46)
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Refaktorieren und kommentieren Sie Ihren Code](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "a4abf305ede1cfaadd56a8fab4b4c288",
|
||||
"translation_date": "2025-08-24T13:37:17+00:00",
|
||||
"source_file": "7-bank-project/3-data/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Refaktorieren und kommentieren Sie Ihren Code
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Wenn Ihre Codebasis wächst, ist es wichtig, den Code regelmäßig zu refaktorieren, um ihn im Laufe der Zeit lesbar und wartbar zu halten. Fügen Sie Kommentare hinzu und refaktorieren Sie Ihre `app.js`, um die Codequalität zu verbessern:
|
||||
|
||||
- Extrahieren Sie Konstanten, wie die Basis-URL der Server-API
|
||||
- Vereinfachen Sie ähnlichen Code: Zum Beispiel können Sie eine `sendRequest()`-Funktion erstellen, um den Code, der sowohl in `createAccount()` als auch in `getAccount()` verwendet wird, zusammenzufassen
|
||||
- Organisieren Sie den Code neu, um ihn leichter lesbar zu machen, und fügen Sie Kommentare hinzu
|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
|
||||
| | Code ist kommentiert, gut organisiert in verschiedene Abschnitte und leicht zu lesen. Konstanten sind extrahiert und eine vereinfachte `sendRequest()`-Funktion wurde erstellt. | Code ist sauber, kann aber durch mehr Kommentare, Konstantenextraktion oder Vereinfachung weiter verbessert werden. | Code ist unübersichtlich, nicht kommentiert, Konstanten sind nicht extrahiert und der Code ist nicht vereinfacht. |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,292 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "4fa20c513e367e9cdd401bf49ae16e33",
|
||||
"translation_date": "2025-08-24T13:44:13+00:00",
|
||||
"source_file": "7-bank-project/4-state-management/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Erstellen einer Banking-App Teil 4: Konzepte des State Managements
|
||||
|
||||
## Quiz vor der Vorlesung
|
||||
|
||||
[Quiz vor der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/47)
|
||||
|
||||
### Einführung
|
||||
|
||||
Mit dem Wachstum einer Webanwendung wird es zunehmend schwieriger, alle Datenflüsse im Blick zu behalten. Welcher Code holt die Daten, welche Seite nutzt sie, wo und wann müssen sie aktualisiert werden... Es ist leicht, in einem unübersichtlichen Code zu enden, der schwer zu warten ist. Dies gilt besonders, wenn Daten zwischen verschiedenen Seiten der App geteilt werden müssen, wie z. B. Benutzerdaten. Das Konzept des *State Managements* existiert schon immer in allen Arten von Programmen, aber mit der zunehmenden Komplexität von Web-Apps ist es heute ein zentraler Punkt, über den man während der Entwicklung nachdenken muss.
|
||||
|
||||
In diesem letzten Teil werden wir die App, die wir erstellt haben, überarbeiten, um das State Management neu zu denken. Dadurch wird es möglich, Browser-Aktualisierungen zu unterstützen und Daten über Benutzersitzungen hinweg zu speichern.
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
Du musst den [Datenabruf](../3-data/README.md)-Teil der Web-App für diese Lektion abgeschlossen haben. Außerdem musst du [Node.js](https://nodejs.org) installieren und die [Server-API](../api/README.md) lokal ausführen, um Kontodaten verwalten zu können.
|
||||
|
||||
Du kannst testen, ob der Server ordnungsgemäß läuft, indem du diesen Befehl in einem Terminal ausführst:
|
||||
|
||||
```sh
|
||||
curl http://localhost:5000/api
|
||||
# -> should return "Bank API v1.0.0" as a result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## State Management überdenken
|
||||
|
||||
In der [vorherigen Lektion](../3-data/README.md) haben wir ein grundlegendes Konzept von State in unserer App eingeführt, indem wir die globale Variable `account` verwendet haben, die die Bankdaten des aktuell angemeldeten Benutzers enthält. Unsere aktuelle Implementierung hat jedoch einige Schwächen. Versuche, die Seite zu aktualisieren, während du auf dem Dashboard bist. Was passiert?
|
||||
|
||||
Es gibt drei Probleme mit dem aktuellen Code:
|
||||
|
||||
- Der State wird nicht gespeichert, da ein Browser-Refresh dich zurück zur Login-Seite bringt.
|
||||
- Es gibt mehrere Funktionen, die den State ändern. Wenn die App wächst, kann es schwierig werden, die Änderungen nachzuverfolgen, und es ist leicht, eine Aktualisierung zu vergessen.
|
||||
- Der State wird nicht bereinigt, sodass die Kontodaten beim Klick auf *Logout* noch vorhanden sind, obwohl du dich auf der Login-Seite befindest.
|
||||
|
||||
Wir könnten unseren Code aktualisieren, um diese Probleme einzeln anzugehen, aber das würde zu mehr Code-Duplikation führen und die App komplexer und schwerer wartbar machen. Oder wir könnten uns ein paar Minuten Zeit nehmen und unsere Strategie überdenken.
|
||||
|
||||
> Welche Probleme versuchen wir hier wirklich zu lösen?
|
||||
|
||||
[State Management](https://de.wikipedia.org/wiki/State_Management) dreht sich darum, einen guten Ansatz zu finden, um diese beiden spezifischen Probleme zu lösen:
|
||||
|
||||
- Wie können die Datenflüsse in einer App verständlich gehalten werden?
|
||||
- Wie kann der State immer mit der Benutzeroberfläche synchronisiert werden (und umgekehrt)?
|
||||
|
||||
Sobald diese Probleme gelöst sind, könnten andere Probleme entweder bereits behoben sein oder leichter zu lösen sein. Es gibt viele mögliche Ansätze, um diese Probleme zu lösen, aber wir werden eine gängige Lösung verwenden, die darin besteht, **die Daten und die Möglichkeiten, sie zu ändern, zu zentralisieren**. Die Datenflüsse würden so aussehen:
|
||||
|
||||

|
||||
|
||||
> Wir werden hier nicht den Teil behandeln, bei dem die Daten automatisch die Ansicht aktualisieren, da dies mit fortgeschritteneren Konzepten der [Reaktiven Programmierung](https://de.wikipedia.org/wiki/Reaktive_Programmierung) verbunden ist. Es ist ein gutes Thema für ein tiefergehendes Studium.
|
||||
|
||||
✅ Es gibt viele Bibliotheken mit unterschiedlichen Ansätzen für das State Management, [Redux](https://redux.js.org) ist eine beliebte Option. Schau dir die Konzepte und Muster an, da sie oft eine gute Möglichkeit bieten, potenzielle Probleme in großen Web-Apps zu verstehen und wie sie gelöst werden können.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Wir beginnen mit ein wenig Refactoring. Ersetze die `account`-Deklaration:
|
||||
|
||||
```js
|
||||
let account = null;
|
||||
```
|
||||
|
||||
Mit:
|
||||
|
||||
```js
|
||||
let state = {
|
||||
account: null
|
||||
};
|
||||
```
|
||||
|
||||
Die Idee ist, *alle Daten unserer App* in einem einzigen State-Objekt zu zentralisieren. Derzeit haben wir nur `account` im State, daher ändert sich nicht viel, aber es schafft eine Grundlage für zukünftige Erweiterungen.
|
||||
|
||||
Wir müssen auch die Funktionen aktualisieren, die es verwenden. Ersetze in den Funktionen `register()` und `login()` `account = ...` durch `state.account = ...`;
|
||||
|
||||
Füge am Anfang der Funktion `updateDashboard()` diese Zeile hinzu:
|
||||
|
||||
```js
|
||||
const account = state.account;
|
||||
```
|
||||
|
||||
Dieses Refactoring bringt für sich genommen nicht viele Verbesserungen, aber die Idee war, die Grundlage für die nächsten Änderungen zu schaffen.
|
||||
|
||||
## Datenänderungen verfolgen
|
||||
|
||||
Jetzt, da wir das `state`-Objekt eingerichtet haben, um unsere Daten zu speichern, ist der nächste Schritt, die Aktualisierungen zu zentralisieren. Das Ziel ist es, es einfacher zu machen, Änderungen und deren Zeitpunkt nachzuverfolgen.
|
||||
|
||||
Um zu vermeiden, dass Änderungen am `state`-Objekt vorgenommen werden, ist es auch eine gute Praxis, es als [*unveränderlich*](https://de.wikipedia.org/wiki/Unveränderliches_Objekt) zu betrachten, was bedeutet, dass es überhaupt nicht geändert werden kann. Das bedeutet auch, dass du ein neues State-Objekt erstellen musst, wenn du etwas daran ändern möchtest. Dadurch schützt du dich vor potenziell unerwünschten [Seiteneffekten](https://de.wikipedia.org/wiki/Seiteneffekt_(Informatik)) und eröffnest Möglichkeiten für neue Funktionen in deiner App, wie z. B. die Implementierung von Undo/Redo, während es auch einfacher wird, Fehler zu debuggen. Zum Beispiel könntest du jede Änderung am State protokollieren und eine Historie der Änderungen führen, um die Quelle eines Fehlers zu verstehen.
|
||||
|
||||
In JavaScript kannst du [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) verwenden, um eine unveränderliche Version eines Objekts zu erstellen. Wenn du versuchst, Änderungen an einem unveränderlichen Objekt vorzunehmen, wird eine Ausnahme ausgelöst.
|
||||
|
||||
✅ Kennst du den Unterschied zwischen einem *flachen* und einem *tiefen* unveränderlichen Objekt? Du kannst darüber [hier](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) lesen.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Lass uns eine neue Funktion `updateState()` erstellen:
|
||||
|
||||
```js
|
||||
function updateState(property, newData) {
|
||||
state = Object.freeze({
|
||||
...state,
|
||||
[property]: newData
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
In dieser Funktion erstellen wir ein neues State-Objekt und kopieren Daten aus dem vorherigen State mithilfe des [*Spread-Operators (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Dann überschreiben wir eine bestimmte Eigenschaft des State-Objekts mit den neuen Daten, indem wir die [Bracket-Notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` für die Zuweisung verwenden. Schließlich sperren wir das Objekt, um Änderungen mit `Object.freeze()` zu verhindern. Derzeit speichern wir nur die `account`-Eigenschaft im State, aber mit diesem Ansatz kannst du so viele Eigenschaften hinzufügen, wie du benötigst.
|
||||
|
||||
Wir aktualisieren auch die `state`-Initialisierung, um sicherzustellen, dass der Anfangszustand ebenfalls eingefroren ist:
|
||||
|
||||
```js
|
||||
let state = Object.freeze({
|
||||
account: null
|
||||
});
|
||||
```
|
||||
|
||||
Danach aktualisieren wir die `register`-Funktion, indem wir die Zuweisung `state.account = result;` durch Folgendes ersetzen:
|
||||
|
||||
```js
|
||||
updateState('account', result);
|
||||
```
|
||||
|
||||
Das Gleiche machen wir mit der `login`-Funktion, indem wir `state.account = data;` durch Folgendes ersetzen:
|
||||
|
||||
```js
|
||||
updateState('account', data);
|
||||
```
|
||||
|
||||
Wir nutzen die Gelegenheit, um das Problem zu beheben, dass die Kontodaten nicht gelöscht werden, wenn der Benutzer auf *Logout* klickt.
|
||||
|
||||
Erstelle eine neue Funktion `logout()`:
|
||||
|
||||
```js
|
||||
function logout() {
|
||||
updateState('account', null);
|
||||
navigate('/login');
|
||||
}
|
||||
```
|
||||
|
||||
Ersetze in `updateDashboard()` die Umleitung `return navigate('/login');` durch `return logout();`;
|
||||
|
||||
Versuche, ein neues Konto zu registrieren, dich abzumelden und erneut anzumelden, um zu überprüfen, ob alles noch korrekt funktioniert.
|
||||
|
||||
> Tipp: Du kannst dir alle State-Änderungen ansehen, indem du `console.log(state)` am Ende von `updateState()` hinzufügst und die Konsole in den Entwicklertools deines Browsers öffnest.
|
||||
|
||||
## Den State speichern
|
||||
|
||||
Die meisten Web-Apps müssen Daten speichern, um korrekt zu funktionieren. Alle kritischen Daten werden normalerweise in einer Datenbank gespeichert und über eine Server-API abgerufen, wie z. B. die Benutzerdaten in unserem Fall. Aber manchmal ist es auch interessant, einige Daten in der Client-App zu speichern, die in deinem Browser läuft, um die Benutzererfahrung zu verbessern oder die Ladeleistung zu steigern.
|
||||
|
||||
Wenn du Daten in deinem Browser speichern möchtest, gibt es einige wichtige Fragen, die du dir stellen solltest:
|
||||
|
||||
- *Sind die Daten sensibel?* Du solltest vermeiden, sensible Daten wie Benutzerpasswörter auf dem Client zu speichern.
|
||||
- *Wie lange möchtest du diese Daten aufbewahren?* Planst du, auf diese Daten nur während der aktuellen Sitzung zuzugreifen, oder sollen sie dauerhaft gespeichert werden?
|
||||
|
||||
Es gibt verschiedene Möglichkeiten, Informationen in einer Web-App zu speichern, je nachdem, was du erreichen möchtest. Zum Beispiel kannst du die URLs verwenden, um eine Suchanfrage zu speichern und sie zwischen Benutzern teilbar zu machen. Du kannst auch [HTTP-Cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) verwenden, wenn die Daten mit dem Server geteilt werden müssen, wie z. B. [Authentifizierungsinformationen](https://de.wikipedia.org/wiki/Authentifizierung).
|
||||
|
||||
Eine andere Option ist die Verwendung einer der vielen Browser-APIs zur Datenspeicherung. Zwei davon sind besonders interessant:
|
||||
|
||||
- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): ein [Key/Value-Store](https://de.wikipedia.org/wiki/Key-Value-Datenbank), der es ermöglicht, datenbankspezifische Daten über verschiedene Sitzungen hinweg zu speichern. Die gespeicherten Daten verfallen nie.
|
||||
- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funktioniert genauso wie `localStorage`, außer dass die darin gespeicherten Daten gelöscht werden, wenn die Sitzung endet (wenn der Browser geschlossen wird).
|
||||
|
||||
Beachte, dass beide APIs nur [Strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) speichern können. Wenn du komplexe Objekte speichern möchtest, musst du sie in das [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-Format serialisieren, indem du [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) verwendest.
|
||||
|
||||
✅ Wenn du eine Web-App erstellen möchtest, die ohne Server funktioniert, ist es auch möglich, eine Datenbank auf dem Client mit der [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) zu erstellen. Diese ist für fortgeschrittene Anwendungsfälle oder wenn du eine erhebliche Menge an Daten speichern musst, da sie komplexer zu verwenden ist.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Wir möchten, dass unsere Benutzer angemeldet bleiben, bis sie explizit auf die Schaltfläche *Logout* klicken. Daher verwenden wir `localStorage`, um die Kontodaten zu speichern. Zuerst definieren wir einen Schlüssel, den wir zum Speichern unserer Daten verwenden.
|
||||
|
||||
```js
|
||||
const storageKey = 'savedAccount';
|
||||
```
|
||||
|
||||
Füge dann diese Zeile am Ende der Funktion `updateState()` hinzu:
|
||||
|
||||
```js
|
||||
localStorage.setItem(storageKey, JSON.stringify(state.account));
|
||||
```
|
||||
|
||||
Damit werden die Benutzerdaten gespeichert und bleiben immer auf dem neuesten Stand, da wir zuvor alle State-Updates zentralisiert haben. Hier beginnen wir, von all unseren vorherigen Refactorings zu profitieren 🙂.
|
||||
|
||||
Da die Daten gespeichert werden, müssen wir uns auch darum kümmern, sie wiederherzustellen, wenn die App geladen wird. Da wir mehr Initialisierungscode haben werden, könnte es eine gute Idee sein, eine neue Funktion `init` zu erstellen, die auch unseren bisherigen Code am Ende von `app.js` enthält:
|
||||
|
||||
```js
|
||||
function init() {
|
||||
const savedAccount = localStorage.getItem(storageKey);
|
||||
if (savedAccount) {
|
||||
updateState('account', JSON.parse(savedAccount));
|
||||
}
|
||||
|
||||
// Our previous initialization code
|
||||
window.onpopstate = () => updateRoute();
|
||||
updateRoute();
|
||||
}
|
||||
|
||||
init();
|
||||
```
|
||||
|
||||
Hier rufen wir die gespeicherten Daten ab, und wenn welche vorhanden sind, aktualisieren wir den State entsprechend. Es ist wichtig, dies *vor* der Aktualisierung der Route zu tun, da es möglicherweise Code gibt, der während der Seitenaktualisierung auf den State angewiesen ist.
|
||||
|
||||
Wir können auch die *Dashboard*-Seite zur Standardseite unserer Anwendung machen, da wir jetzt die Kontodaten speichern. Wenn keine Daten gefunden werden, kümmert sich das Dashboard ohnehin um die Weiterleitung zur *Login*-Seite. Ersetze in `updateRoute()` den Fallback `return navigate('/login');` durch `return navigate('/dashboard');`.
|
||||
|
||||
Melde dich jetzt in der App an und versuche, die Seite zu aktualisieren. Du solltest auf dem Dashboard bleiben. Mit diesem Update haben wir alle unsere anfänglichen Probleme gelöst...
|
||||
|
||||
## Daten aktualisieren
|
||||
|
||||
...Aber wir könnten auch ein neues Problem geschaffen haben. Ups!
|
||||
|
||||
Gehe mit dem `test`-Konto zum Dashboard und führe dann diesen Befehl in einem Terminal aus, um eine neue Transaktion zu erstellen:
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
|
||||
http://localhost:5000/api/accounts/test/transactions
|
||||
```
|
||||
|
||||
Versuche jetzt, die Dashboard-Seite im Browser zu aktualisieren. Was passiert? Siehst du die neue Transaktion?
|
||||
|
||||
Der State wird dank `localStorage` unbegrenzt gespeichert, aber das bedeutet auch, dass er nie aktualisiert wird, bis du dich aus der App abmeldest und wieder anmeldest!
|
||||
|
||||
Eine mögliche Strategie, um das zu beheben, ist, die Kontodaten jedes Mal neu zu laden, wenn das Dashboard geladen wird, um veraltete Daten zu vermeiden.
|
||||
|
||||
### Aufgabe
|
||||
|
||||
Erstelle eine neue Funktion `updateAccountData`:
|
||||
|
||||
```js
|
||||
async function updateAccountData() {
|
||||
const account = state.account;
|
||||
if (!account) {
|
||||
return logout();
|
||||
}
|
||||
|
||||
const data = await getAccount(account.user);
|
||||
if (data.error) {
|
||||
return logout();
|
||||
}
|
||||
|
||||
updateState('account', data);
|
||||
}
|
||||
```
|
||||
|
||||
Diese Methode überprüft, ob wir derzeit angemeldet sind, und lädt dann die Kontodaten vom Server neu.
|
||||
|
||||
Erstelle eine weitere Funktion namens `refresh`:
|
||||
|
||||
```js
|
||||
async function refresh() {
|
||||
await updateAccountData();
|
||||
updateDashboard();
|
||||
}
|
||||
```
|
||||
|
||||
Diese Funktion aktualisiert die Kontodaten und kümmert sich dann um die Aktualisierung des HTMLs der Dashboard-Seite. Sie ist das, was wir aufrufen müssen, wenn die Dashboard-Route geladen wird. Aktualisiere die Routen-Definition mit:
|
||||
|
||||
```js
|
||||
const routes = {
|
||||
'/login': { templateId: 'login' },
|
||||
'/dashboard': { templateId: 'dashboard', init: refresh }
|
||||
};
|
||||
```
|
||||
|
||||
Versuche jetzt, das Dashboard zu aktualisieren. Es sollte die aktualisierten Kontodaten anzeigen.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Herausforderung
|
||||
|
||||
Da wir die Kontodaten jedes Mal neu laden, wenn das Dashboard geladen wird, denkst du, dass wir *alle Kontodaten* weiterhin speichern müssen?
|
||||
|
||||
Versuche gemeinsam zu erarbeiten, was in `localStorage` gespeichert und geladen werden sollte, um nur das zu enthalten, was absolut notwendig ist, damit die App funktioniert.
|
||||
|
||||
## Quiz nach der Vorlesung
|
||||
[Quiz nach der Vorlesung](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/48)
|
||||
|
||||
## Aufgabe
|
||||
|
||||
[Implementieren Sie den Dialog "Transaktion hinzufügen"](assignment.md)
|
||||
|
||||
Hier ist ein Beispielergebnis nach Abschluss der Aufgabe:
|
||||
|
||||

|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,37 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "f23a868536c07da991b1d4e773161e25",
|
||||
"translation_date": "2025-08-24T13:47:39+00:00",
|
||||
"source_file": "7-bank-project/4-state-management/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Implementieren Sie den Dialog "Transaktion hinzufügen"
|
||||
|
||||
## Anweisungen
|
||||
|
||||
Unsere Banking-App fehlt noch eine wichtige Funktion: die Möglichkeit, neue Transaktionen einzugeben.
|
||||
Nutzen Sie alles, was Sie in den vier vorherigen Lektionen gelernt haben, um einen Dialog "Transaktion hinzufügen" zu implementieren:
|
||||
|
||||
- Fügen Sie einen Button "Transaktion hinzufügen" auf der Dashboard-Seite hinzu.
|
||||
- Erstellen Sie entweder eine neue Seite mit einer HTML-Vorlage oder verwenden Sie JavaScript, um das Dialog-HTML ein- und auszublenden, ohne die Dashboard-Seite zu verlassen (Sie können dafür die [`hidden`](https://developer.mozilla.org/docs/Web/HTML/Global_attributes/hidden)-Eigenschaft oder CSS-Klassen verwenden).
|
||||
- Stellen Sie sicher, dass Sie [Tastatur- und Screenreader-Zugänglichkeit](https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/) für den Dialog berücksichtigen.
|
||||
- Implementieren Sie ein HTML-Formular, um Eingabedaten zu erfassen.
|
||||
- Erstellen Sie JSON-Daten aus den Formulardaten und senden Sie diese an die API.
|
||||
- Aktualisieren Sie die Dashboard-Seite mit den neuen Daten.
|
||||
|
||||
Schauen Sie sich die [Server-API-Spezifikationen](../api/README.md) an, um zu sehen, welche API Sie aufrufen müssen und welches JSON-Format erwartet wird.
|
||||
|
||||
Hier ist ein Beispielergebnis nach Abschluss der Aufgabe:
|
||||
|
||||

|
||||
|
||||
## Bewertungskriterien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
|
||||
| | Das Hinzufügen einer Transaktion ist vollständig implementiert und folgt allen Best Practices aus den Lektionen. | Das Hinzufügen einer Transaktion ist implementiert, folgt jedoch nicht den Best Practices aus den Lektionen oder funktioniert nur teilweise. | Das Hinzufügen einer Transaktion funktioniert überhaupt nicht. |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,33 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "830359535306594b448db6575ce5cdee",
|
||||
"translation_date": "2025-08-24T13:26:08+00:00",
|
||||
"source_file": "7-bank-project/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# :dollar: Baue eine Bank
|
||||
|
||||
In diesem Projekt lernst du, wie man eine fiktive Bank erstellt. Diese Lektionen enthalten Anleitungen, wie man eine Web-App gestaltet und Routen bereitstellt, Formulare erstellt, den Zustand verwaltet und Daten von einer API abruft, um die Bankdaten zu erhalten.
|
||||
|
||||
|  |  |
|
||||
|--------------------------------|--------------------------------|
|
||||
|
||||
## Lektionen
|
||||
|
||||
1. [HTML-Templates und Routen in einer Web-App](1-template-route/README.md)
|
||||
2. [Erstellen eines Login- und Registrierungsformulars](2-forms/README.md)
|
||||
3. [Methoden zum Abrufen und Verwenden von Daten](3-data/README.md)
|
||||
4. [Konzepte des Zustandsmanagements](4-state-management/README.md)
|
||||
|
||||
### Credits
|
||||
|
||||
Diese Lektionen wurden mit :hearts: von [Yohan Lasorsa](https://twitter.com/sinedied) geschrieben.
|
||||
|
||||
Wenn du lernen möchtest, wie man die [Server-API](/7-bank-project/api/README.md) erstellt, die in diesen Lektionen verwendet wird, kannst du [diese Videoserie](https://aka.ms/NodeBeginner) verfolgen (insbesondere die Videos 17 bis 21).
|
||||
|
||||
Du kannst dir auch [dieses interaktive Learn-Tutorial](https://aka.ms/learn/express-api) ansehen.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,46 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "9884f8c8a61cf56214450f8b16a094ce",
|
||||
"translation_date": "2025-08-24T13:27:01+00:00",
|
||||
"source_file": "7-bank-project/api/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Bank-API
|
||||
|
||||
> Bank-API erstellt mit [Node.js](https://nodejs.org) + [Express](https://expressjs.com/).
|
||||
|
||||
Die API ist bereits für Sie erstellt und nicht Teil der Übung.
|
||||
|
||||
Falls Sie jedoch daran interessiert sind, zu lernen, wie man eine solche API erstellt, können Sie diese Videoserie verfolgen: https://aka.ms/NodeBeginner (Videos 17 bis 21 behandeln genau diese API).
|
||||
|
||||
Sie können sich auch dieses interaktive Tutorial ansehen: https://aka.ms/learn/express-api
|
||||
|
||||
## Server starten
|
||||
|
||||
Stellen Sie sicher, dass [Node.js](https://nodejs.org) installiert ist.
|
||||
|
||||
1. Klonen Sie dieses Repository: [The Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners).
|
||||
2. Öffnen Sie Ihr Terminal und navigieren Sie in den Ordner `Web-Dev-For-Beginners/7-bank-project/api`.
|
||||
3. Führen Sie `npm install` aus und warten Sie, bis die Pakete installiert sind (dies kann je nach Qualität Ihrer Internetverbindung eine Weile dauern).
|
||||
4. Wenn die Installation abgeschlossen ist, führen Sie `npm start` aus, und Sie sind startklar.
|
||||
|
||||
Der Server sollte auf Port `5000` lauschen.
|
||||
*Dieser Server wird zusammen mit dem Hauptserver der Bank-App (lauscht auf Port `3000`) ausgeführt. Schließen Sie ihn nicht.*
|
||||
|
||||
> Hinweis: Alle Einträge werden im Arbeitsspeicher gespeichert und nicht dauerhaft gesichert. Wenn der Server gestoppt wird, gehen alle Daten verloren.
|
||||
|
||||
## API-Details
|
||||
|
||||
Route | Beschreibung
|
||||
---------------------------------------------|------------------------------------
|
||||
GET /api/ | Serverinformationen abrufen
|
||||
POST /api/accounts/ | Ein Konto erstellen, z. B.: `{ user: 'Yohan', description: 'Mein Budget', currency: 'EUR', balance: 100 }`
|
||||
GET /api/accounts/:user | Alle Daten für das angegebene Konto abrufen
|
||||
DELETE /api/accounts/:user | Angegebenes Konto entfernen
|
||||
POST /api/accounts/:user/transactions | Eine Transaktion hinzufügen, z. B.: `{ date: '2020-07-23T18:25:43.511Z', object: 'Ein Buch gekauft', amount: -20 }`
|
||||
DELETE /api/accounts/:user/transactions/:id | Angegebene Transaktion entfernen
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "461aa4fc74c6b1789c3a13b5d82c0cd9",
|
||||
"translation_date": "2025-08-24T13:42:32+00:00",
|
||||
"source_file": "7-bank-project/solution/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Bank-App
|
||||
|
||||
> Beispiel-Lösung für das Bank-App-Projekt, erstellt mit reinem HTML5, CSS und JavaScript (ohne Frameworks oder Bibliotheken).
|
||||
|
||||
## App ausführen
|
||||
|
||||
Stellen Sie zunächst sicher, dass der [API-Server](../api/README.md) läuft.
|
||||
|
||||
Jeder Webserver kann verwendet werden, um die App auszuführen, aber da Sie ohnehin [Node.js](https://nodejs.org) installiert haben sollten, um die API auszuführen, können Sie:
|
||||
|
||||
1. Dieses Repository mit Git klonen.
|
||||
2. Öffnen Sie ein Terminal, navigieren Sie zu diesem Verzeichnis und führen Sie dann `npx lite-server .` aus. Dadurch wird ein Entwicklungs-Webserver auf Port `3000` gestartet.
|
||||
3. Öffnen Sie `http://localhost:3000` in einem Browser, um die App auszuführen.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "b0a9b4cccd918195f58224d5793da1a6",
|
||||
"translation_date": "2025-08-24T11:55:34+00:00",
|
||||
"source_file": "CODE_OF_CONDUCT.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Microsoft Open Source Verhaltenskodex
|
||||
|
||||
Dieses Projekt hat den [Microsoft Open Source Verhaltenskodex](https://opensource.microsoft.com/codeofconduct/?WT.mc_id=academic-77807-sagibbon) übernommen.
|
||||
|
||||
Ressourcen:
|
||||
|
||||
- [Microsoft Open Source Verhaltenskodex](https://opensource.microsoft.com/codeofconduct/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [Microsoft Verhaltenskodex FAQ](https://opensource.microsoft.com/codeofconduct/faq/?WT.mc_id=academic-77807-sagibbon)
|
||||
- Kontaktieren Sie [opencode@microsoft.com](mailto:opencode@microsoft.com) bei Fragen oder Bedenken
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "777400e9f0336c7ee2f9a1200a88478f",
|
||||
"translation_date": "2025-08-24T11:57:57+00:00",
|
||||
"source_file": "CONTRIBUTING.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Mitwirken
|
||||
|
||||
Dieses Projekt freut sich über Beiträge und Vorschläge. Die meisten Beiträge erfordern, dass Sie einer Contributor License Agreement (CLA) zustimmen, in der Sie erklären, dass Sie das Recht haben und uns tatsächlich die Rechte einräumen, Ihren Beitrag zu nutzen. Weitere Details finden Sie unter [https://cla.microsoft.com](https://cla.microsoft.com/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
Wenn Sie einen Pull Request einreichen, wird ein CLA-Bot automatisch überprüfen, ob Sie eine CLA bereitstellen müssen, und den PR entsprechend kennzeichnen (z. B. mit einem Label oder Kommentar). Folgen Sie einfach den Anweisungen des Bots. Dies müssen Sie nur einmal für alle Repositories tun, die unsere CLA verwenden. Bitte versuchen Sie auch, uns mitzuteilen, warum Sie diese Änderung vorgenommen haben, damit wir Ihre Anfrage besser verstehen können.
|
||||
|
||||
Dieses Projekt hat den [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/?WT.mc_id=academic-77807-sagibbon) übernommen.
|
||||
Weitere Informationen finden Sie in den [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/?WT.mc_id=academic-77807-sagibbon) oder kontaktieren Sie [opencode@microsoft.com](mailto:opencode@microsoft.com) bei weiteren Fragen oder Anmerkungen.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,49 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "4ecc3bf2e27983d4c780be6f26ee6228",
|
||||
"translation_date": "2025-08-24T11:56:51+00:00",
|
||||
"source_file": "SECURITY.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
## Sicherheit
|
||||
|
||||
Microsoft nimmt die Sicherheit seiner Softwareprodukte und -dienste sehr ernst, einschließlich aller Quellcode-Repositories, die über unsere GitHub-Organisationen verwaltet werden. Dazu gehören [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin) und [unsere GitHub-Organisationen](https://opensource.microsoft.com/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
Wenn Sie der Meinung sind, eine Sicherheitslücke in einem von Microsoft verwalteten Repository gefunden zu haben, die [Microsofts Definition einer Sicherheitslücke](https://docs.microsoft.com/previous-versions/tn-archive/cc751383(v=technet.10)/?WT.mc_id=academic-77807-sagibbon) entspricht, melden Sie diese bitte wie unten beschrieben.
|
||||
|
||||
## Melden von Sicherheitsproblemen
|
||||
|
||||
**Bitte melden Sie Sicherheitslücken nicht über öffentliche GitHub-Issues.**
|
||||
|
||||
Stattdessen melden Sie diese bitte dem Microsoft Security Response Center (MSRC) unter [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
Falls Sie lieber ohne Anmeldung einreichen möchten, senden Sie eine E-Mail an [secure@microsoft.com](mailto:secure@microsoft.com). Wenn möglich, verschlüsseln Sie Ihre Nachricht mit unserem PGP-Schlüssel; laden Sie diesen von der [Microsoft Security Response Center PGP Key-Seite](https://www.microsoft.com/msrc/pgp-key-msrc/?WT.mc_id=academic-77807-sagibbon) herunter.
|
||||
|
||||
Sie sollten innerhalb von 24 Stunden eine Antwort erhalten. Falls dies aus irgendeinem Grund nicht der Fall ist, senden Sie bitte eine Nachfass-E-Mail, um sicherzustellen, dass wir Ihre ursprüngliche Nachricht erhalten haben. Weitere Informationen finden Sie unter [microsoft.com/msrc](https://www.microsoft.com/msrc/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
Bitte fügen Sie die unten aufgeführten Informationen (so weit wie möglich) bei, um uns zu helfen, die Art und den Umfang des möglichen Problems besser zu verstehen:
|
||||
|
||||
* Art des Problems (z. B. Buffer Overflow, SQL Injection, Cross-Site Scripting usw.)
|
||||
* Vollständige Pfade der Quellcodedatei(en), die mit dem Problem in Zusammenhang stehen
|
||||
* Der Ort des betroffenen Quellcodes (Tag/Branch/Commit oder direkte URL)
|
||||
* Besondere Konfigurationen, die erforderlich sind, um das Problem zu reproduzieren
|
||||
* Schritt-für-Schritt-Anleitung zur Reproduktion des Problems
|
||||
* Proof-of-Concept- oder Exploit-Code (falls möglich)
|
||||
* Auswirkungen des Problems, einschließlich der möglichen Ausnutzung durch einen Angreifer
|
||||
|
||||
Diese Informationen helfen uns, Ihren Bericht schneller zu priorisieren.
|
||||
|
||||
Wenn Sie im Rahmen eines Bug-Bounty-Programms berichten, können vollständigere Berichte zu einer höheren Prämie führen. Besuchen Sie unsere Seite zum [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty/?WT.mc_id=academic-77807-sagibbon) für weitere Details zu unseren aktiven Programmen.
|
||||
|
||||
## Bevorzugte Sprachen
|
||||
|
||||
Wir bevorzugen, dass alle Mitteilungen auf Englisch erfolgen.
|
||||
|
||||
## Richtlinie
|
||||
|
||||
Microsoft folgt dem Prinzip der [Koordinierten Offenlegung von Sicherheitslücken](https://www.microsoft.com/msrc/cvd/?WT.mc_id=academic-77807-sagibbon).
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "c9d207ff77b4bb46e46dc2b607a8ec1a",
|
||||
"translation_date": "2025-08-24T11:53:43+00:00",
|
||||
"source_file": "SUPPORT.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Unterstützung
|
||||
|
||||
## So melden Sie Probleme und erhalten Hilfe
|
||||
|
||||
Dieses Projekt verwendet GitHub Issues, um Fehler und Funktionsanfragen zu verfolgen. Bitte durchsuchen Sie die vorhandenen Issues, bevor Sie neue erstellen, um Duplikate zu vermeiden. Für neue Issues melden Sie Ihren Fehler oder Ihre Funktionsanfrage als neues Issue.
|
||||
|
||||
Für Hilfe und Fragen zur Nutzung dieses Projekts lesen Sie bitte [unsere Beitragsrichtlinien](CONTRIBUTING.md).
|
||||
|
||||
## Microsoft-Support-Richtlinie
|
||||
|
||||
Der Support für dieses Projekt ist auf die oben aufgeführten Ressourcen beschränkt.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,19 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "ea9f0804bd62f46d9808e953ec7fc459",
|
||||
"translation_date": "2025-08-24T11:56:09+00:00",
|
||||
"source_file": "_404.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# Arbeit läuft
|
||||
|
||||
Wir arbeiten an dieser Seite. Bitte schauen Sie später noch einmal vorbei.
|
||||
|
||||
Öffnen Sie ein [Issue](https://github.com/microsoft/Web-Dev-For-Beginners/issues/new/choose), wenn Sie Fragen haben.
|
||||
|
||||
**[Zurück zur Startseite](../../../../../../..)**
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,32 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "3bd2f51ecf4ac9b39277cba748943793",
|
||||
"translation_date": "2025-08-24T12:25:44+00:00",
|
||||
"source_file": "docs/_navbar.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
- Übersetzungen
|
||||
- [English (United States)](../../../docs/README)
|
||||
- [বাংলা](../../../docs/README.bn)
|
||||
- [中文(中国)](../../../docs/README.zh-cn)
|
||||
- [中文(台湾)](../../../docs/README.zh-tw)
|
||||
- [Español](../../../docs/README.es)
|
||||
- [Français](../../../docs/README.fr)
|
||||
- [Ελληνικά](../../../docs/README.el)
|
||||
- [हिन्दी](../../../docs/README.hi)
|
||||
- [Bahasa Melayu](../../../docs/README.ms)
|
||||
- [മലയാളം](../../../docs/README.ml)
|
||||
- [தமிழ்](../../../docs/README.ta)
|
||||
- [తెలుగు](../../../docs/README.te)
|
||||
- [Bahasa Indonesia](../../../docs/README.id)
|
||||
- [Italiano](../../../docs/README.it)
|
||||
- [日本語](../../../docs/README.ja)
|
||||
- [Nederlands](../../../docs/README.nl)
|
||||
- [नेपाली](../../../docs/README.np)
|
||||
- [Português](../../../docs/README.pt)
|
||||
- [Русский](../../../docs/README.ru)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,49 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "655c91b5979de46f1d70d97f0c5f1d14",
|
||||
"translation_date": "2025-08-24T12:24:49+00:00",
|
||||
"source_file": "docs/_sidebar.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
- Einführung
|
||||
- [1](../1-getting-started-lessons/1-intro-to-programming-languages/README.md)
|
||||
- [2](../1-getting-started-lessons/2-github-basics/README.md)
|
||||
- [3](../1-getting-started-lessons/3-accessibility/README.md)
|
||||
|
||||
- JS-Grundlagen
|
||||
- [4](../2-js-basics/1-data-types/README.md)
|
||||
- [5](../2-js-basics/2-functions-methods/README.md)
|
||||
- [6](../2-js-basics/3-making-decisions/README.md)
|
||||
- [7](../2-js-basics/4-arrays-loops/README.md)
|
||||
|
||||
- HTML, CSS, JS
|
||||
- [8](../3-terrarium/1-intro-to-html/README.md)
|
||||
- [9](../3-terrarium/2-intro-to-css/README.md)
|
||||
- [10](../3-terrarium/3-intro-to-DOM-and-closures/README.md)
|
||||
|
||||
- Tipp-Spiel
|
||||
- [11](../4-typing-game/typing-game/README.md)
|
||||
|
||||
- Browser-Erweiterung
|
||||
- [12](../5-browser-extension/1-about-browsers/README.md)
|
||||
- [13](../5-browser-extension/2-forms-browsers-local-storage/README.md)
|
||||
- [14](../5-browser-extension/3-background-tasks-and-performance/README.md)
|
||||
|
||||
- Weltraumspiel
|
||||
- [15](../6-space-game/1-introduction/README.md)
|
||||
- [16](../6-space-game/2-drawing-to-canvas/README.md)
|
||||
- [17](../6-space-game/3-moving-elements-around/README.md)
|
||||
- [18](../6-space-game/4-collision-detection/README.md)
|
||||
- [19](../6-space-game/5-keeping-score/README.md)
|
||||
- [20](../6-space-game/6-end-condition/README.md)
|
||||
|
||||
- Bankprojekt
|
||||
- [21](../7-bank-project/1-template-route/README.md)
|
||||
- [22](../7-bank-project/2-forms/README.md)
|
||||
- [23](../7-bank-project/3-data/README.md)
|
||||
- [24](../7-bank-project/4-state-management/README.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir haften nicht für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,45 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "75cb51f7ca9ea0b097ef4a1287e9290c",
|
||||
"translation_date": "2025-08-24T11:54:33+00:00",
|
||||
"source_file": "for-teachers.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
## Für Lehrkräfte
|
||||
|
||||
Möchten Sie dieses Curriculum in Ihrem Unterricht verwenden? Sehr gerne!
|
||||
|
||||
Tatsächlich können Sie es direkt auf GitHub nutzen, indem Sie GitHub Classroom verwenden.
|
||||
|
||||
Dazu müssen Sie dieses Repository forken. Sie benötigen ein separates Repository für jede Lektion, daher müssen Sie jeden Ordner in ein eigenes Repository extrahieren. Auf diese Weise kann [GitHub Classroom](https://classroom.github.com/classrooms) jede Lektion einzeln erfassen.
|
||||
|
||||
Diese [vollständigen Anweisungen](https://github.blog/2020-03-18-set-up-your-digital-classroom-with-github-classroom/) geben Ihnen eine Vorstellung davon, wie Sie Ihr Klassenzimmer einrichten können.
|
||||
|
||||
## Nutzung in Moodle, Canvas oder Blackboard
|
||||
|
||||
Dieses Curriculum funktioniert hervorragend in diesen Learning Management Systemen! Verwenden Sie die [Moodle-Datei](../../../../../../../teaching-files/webdev-moodle.mbz) für den vollständigen Inhalt oder probieren Sie die [Common Cartridge-Datei](../../../../../../../teaching-files/webdev-common-cartridge.imscc), die einen Teil des Inhalts enthält. Moodle Cloud unterstützt keine vollständigen Common Cartridge-Exporte, daher ist es besser, die Moodle-Download-Datei zu verwenden, die in Canvas hochgeladen werden kann. Bitte teilen Sie uns mit, wie wir diese Erfahrung verbessern können.
|
||||
|
||||

|
||||
> Das Curriculum in einem Moodle-Klassenzimmer
|
||||
|
||||

|
||||
> Das Curriculum in Canvas
|
||||
|
||||
## Nutzung des Repos in der aktuellen Form
|
||||
|
||||
Wenn Sie dieses Repository in seiner aktuellen Form verwenden möchten, ohne GitHub Classroom zu nutzen, ist das ebenfalls möglich. Sie müssten Ihren Schülern mitteilen, welche Lektion Sie gemeinsam durcharbeiten möchten.
|
||||
|
||||
In einem Online-Format (Zoom, Teams oder andere) könnten Sie Breakout-Räume für die Quizfragen bilden und die Schüler betreuen, um sie auf das Lernen vorzubereiten. Anschließend laden Sie die Schüler zu den Quizfragen ein und lassen sie ihre Antworten zu einem bestimmten Zeitpunkt als 'Issues' einreichen. Dasselbe könnten Sie mit Aufgaben machen, wenn Sie möchten, dass die Schüler offen und kollaborativ arbeiten.
|
||||
|
||||
Wenn Sie ein privateres Format bevorzugen, bitten Sie Ihre Schüler, das Curriculum Lektion für Lektion in ihre eigenen privaten GitHub-Repositories zu forken und Ihnen Zugriff zu gewähren. Dann können sie Quizfragen und Aufgaben privat bearbeiten und diese über Issues in Ihrem Klassenzimmer-Repository einreichen.
|
||||
|
||||
Es gibt viele Möglichkeiten, dies in einem Online-Klassenzimmer-Format umzusetzen. Bitte teilen Sie uns mit, was für Sie am besten funktioniert!
|
||||
|
||||
## Teilen Sie uns Ihre Meinung mit!
|
||||
|
||||
Wir möchten dieses Curriculum für Sie und Ihre Schüler optimal gestalten. Kontaktieren Sie uns in der [Lehrerecke](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner) und eröffnen Sie ein [**neues Issue**](https://github.com/microsoft/Web-Dev-For-Beginners/issues/new/choose) für Anfragen, Fehler und Feedback.
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,63 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "0494be70ad7fadd13a8c3d549c23e355",
|
||||
"translation_date": "2025-08-24T13:48:27+00:00",
|
||||
"source_file": "lesson-template/README.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# [Lektionsthema]
|
||||
|
||||

|
||||
|
||||
## [Quiz vor der Vorlesung](../../../lesson-template/quiz-url)
|
||||
|
||||
[Beschreiben, was wir lernen werden]
|
||||
|
||||
### Einführung
|
||||
|
||||
Beschreiben, was behandelt wird
|
||||
|
||||
> Notizen
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
Welche Schritte sollten vor dieser Lektion abgeschlossen sein?
|
||||
|
||||
### Vorbereitung
|
||||
|
||||
Vorbereitende Schritte, um mit dieser Lektion zu beginnen
|
||||
|
||||
---
|
||||
|
||||
[Inhalt blockweise durchgehen]
|
||||
|
||||
## [Thema 1]
|
||||
|
||||
### Aufgabe:
|
||||
|
||||
Arbeitet gemeinsam daran, euren Code schrittweise zu verbessern, um das Projekt mit gemeinsamem Code aufzubauen:
|
||||
|
||||
```html
|
||||
code blocks
|
||||
```
|
||||
|
||||
✅ Wissensüberprüfung - nutzt diesen Moment, um das Wissen der Studierenden mit offenen Fragen zu erweitern
|
||||
|
||||
## [Thema 2]
|
||||
|
||||
## [Thema 3]
|
||||
|
||||
🚀 Herausforderung: Fügt eine Herausforderung hinzu, an der die Studierenden im Unterricht gemeinsam arbeiten können, um das Projekt zu verbessern
|
||||
|
||||
Optional: Füge einen Screenshot der Benutzeroberfläche der abgeschlossenen Lektion hinzu, falls passend
|
||||
|
||||
## [Quiz nach der Vorlesung](../../../lesson-template/quiz-url)
|
||||
|
||||
## Rückblick & Selbststudium
|
||||
|
||||
**Abgabe fällig [MM/JJ]**: [Aufgabenname](assignment.md)
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben.
|
||||
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "b5f62ec256c7e43e771f0d3b4e1a9130",
|
||||
"translation_date": "2025-08-24T13:49:06+00:00",
|
||||
"source_file": "lesson-template/assignment.md",
|
||||
"language_code": "de"
|
||||
}
|
||||
-->
|
||||
# [Aufgabenname]
|
||||
|
||||
## Anweisungen
|
||||
|
||||
## Bewertungsrichtlinien
|
||||
|
||||
| Kriterien | Vorbildlich | Angemessen | Verbesserungswürdig |
|
||||
| --------- | ----------- | ---------- | -------------------- |
|
||||
| | | | |
|
||||
|
||||
**Haftungsausschluss**:
|
||||
Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
|
||||
@ -0,0 +1,215 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "c63675cfaf1d223b37bb9fecbfe7c252",
|
||||
"translation_date": "2025-08-24T12:58:14+00:00",
|
||||
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Introducción a los Lenguajes de Programación y Herramientas del Oficio
|
||||
|
||||
Esta lección cubre los conceptos básicos de los lenguajes de programación. Los temas tratados aquí se aplican a la mayoría de los lenguajes de programación modernos. En la sección "Herramientas del Oficio", aprenderás sobre software útil que te ayudará como desarrollador.
|
||||
|
||||

|
||||
> Sketchnote por [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Cuestionario Previo a la Clase
|
||||
[Cuestionario previo a la clase](https://forms.office.com/r/dru4TE0U9n?origin=lprLink)
|
||||
|
||||
## Introducción
|
||||
|
||||
En esta lección, cubriremos:
|
||||
|
||||
- ¿Qué es la programación?
|
||||
- Tipos de lenguajes de programación
|
||||
- Elementos básicos de un programa
|
||||
- Software y herramientas útiles para el desarrollador profesional
|
||||
|
||||
> Puedes tomar esta lección en [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/introduction-programming/?WT.mc_id=academic-77807-sagibbon)!
|
||||
|
||||
## ¿Qué es la Programación?
|
||||
|
||||
La programación (también conocida como codificación) es el proceso de escribir instrucciones para un dispositivo como una computadora o un dispositivo móvil. Escribimos estas instrucciones con un lenguaje de programación, que luego es interpretado por el dispositivo. Estos conjuntos de instrucciones pueden ser referidos con varios nombres, pero *programa*, *programa de computadora*, *aplicación (app)* y *ejecutable* son algunos nombres populares.
|
||||
|
||||
Un *programa* puede ser cualquier cosa escrita con código; sitios web, juegos y aplicaciones móviles son programas. Aunque es posible crear un programa sin escribir código, la lógica subyacente es interpretada por el dispositivo y esa lógica probablemente fue escrita con código. Un programa que está *ejecutando* o *procesando* código está llevando a cabo instrucciones. El dispositivo con el que estás leyendo esta lección está ejecutando un programa para mostrarla en tu pantalla.
|
||||
|
||||
✅ Investiga un poco: ¿Quién es considerado el primer programador de computadoras del mundo?
|
||||
|
||||
## Lenguajes de Programación
|
||||
|
||||
Los lenguajes de programación permiten a los desarrolladores escribir instrucciones para un dispositivo. Los dispositivos solo pueden entender binario (1s y 0s), y para *la mayoría* de los desarrolladores, esa no es una forma muy eficiente de comunicarse. Los lenguajes de programación son el vehículo para la comunicación entre humanos y computadoras.
|
||||
|
||||
Los lenguajes de programación vienen en diferentes formatos y pueden servir diferentes propósitos. Por ejemplo, JavaScript se utiliza principalmente para aplicaciones web, mientras que Bash se utiliza principalmente para sistemas operativos.
|
||||
|
||||
Los *lenguajes de bajo nivel* generalmente requieren menos pasos que los *lenguajes de alto nivel* para que un dispositivo interprete las instrucciones. Sin embargo, lo que hace populares a los lenguajes de alto nivel es su legibilidad y soporte. JavaScript se considera un lenguaje de alto nivel.
|
||||
|
||||
El siguiente código ilustra la diferencia entre un lenguaje de alto nivel con JavaScript y un lenguaje de bajo nivel con código ensamblador ARM.
|
||||
|
||||
```javascript
|
||||
let number = 10
|
||||
let n1 = 0, n2 = 1, nextTerm;
|
||||
|
||||
for (let i = 1; i <= number; i++) {
|
||||
console.log(n1);
|
||||
nextTerm = n1 + n2;
|
||||
n1 = n2;
|
||||
n2 = nextTerm;
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
area ascen,code,readonly
|
||||
entry
|
||||
code32
|
||||
adr r0,thumb+1
|
||||
bx r0
|
||||
code16
|
||||
thumb
|
||||
mov r0,#00
|
||||
sub r0,r0,#01
|
||||
mov r1,#01
|
||||
mov r4,#10
|
||||
ldr r2,=0x40000000
|
||||
back add r0,r1
|
||||
str r0,[r2]
|
||||
add r2,#04
|
||||
mov r3,r0
|
||||
mov r0,r1
|
||||
mov r1,r3
|
||||
sub r4,#01
|
||||
cmp r4,#00
|
||||
bne back
|
||||
end
|
||||
```
|
||||
|
||||
Aunque no lo creas, *ambos están haciendo lo mismo*: imprimir una secuencia de Fibonacci hasta el número 10.
|
||||
|
||||
✅ Una secuencia de Fibonacci se [define](https://en.wikipedia.org/wiki/Fibonacci_number) como un conjunto de números en el que cada número es la suma de los dos anteriores, comenzando desde 0 y 1. Los primeros 10 números de la secuencia de Fibonacci son 0, 1, 1, 2, 3, 5, 8, 13, 21 y 34.
|
||||
|
||||
## Elementos de un Programa
|
||||
|
||||
Una sola instrucción en un programa se llama *sentencia* y usualmente tendrá un carácter o espacio de línea que marca dónde termina la instrucción, o *termina*. Cómo termina un programa varía según el lenguaje.
|
||||
|
||||
Las sentencias dentro de un programa pueden depender de datos proporcionados por un usuario o de otro lugar para llevar a cabo instrucciones. Los datos pueden cambiar cómo se comporta un programa, por lo que los lenguajes de programación vienen con una forma de almacenar datos temporalmente para que puedan ser utilizados más tarde. Estos se llaman *variables*. Las variables son sentencias que instruyen a un dispositivo a guardar datos en su memoria. Las variables en los programas son similares a las variables en álgebra, donde tienen un nombre único y su valor puede cambiar con el tiempo.
|
||||
|
||||
Es posible que algunas sentencias no sean ejecutadas por un dispositivo. Esto generalmente ocurre por diseño cuando lo escribe el desarrollador o por accidente cuando ocurre un error inesperado. Este tipo de control sobre una aplicación la hace más robusta y mantenible. Típicamente, estos cambios en el control ocurren cuando se cumplen ciertas condiciones. Una sentencia común utilizada en la programación moderna para controlar cómo se ejecuta un programa es la sentencia `if..else`.
|
||||
|
||||
✅ Aprenderás más sobre este tipo de sentencia en lecciones posteriores.
|
||||
|
||||
## Herramientas del Oficio
|
||||
|
||||
[](https://youtube.com/watch?v=69WJeXGBdxg "Herramientas del Oficio")
|
||||
|
||||
> 🎥 Haz clic en la imagen de arriba para ver un video sobre herramientas
|
||||
|
||||
En esta sección, aprenderás sobre algunos programas que pueden ser muy útiles al comenzar tu camino como desarrollador profesional.
|
||||
|
||||
Un **entorno de desarrollo** es un conjunto único de herramientas y características que un desarrollador utiliza frecuentemente al escribir software. Algunas de estas herramientas han sido personalizadas para las necesidades específicas de un desarrollador y pueden cambiar con el tiempo si ese desarrollador cambia prioridades en el trabajo, proyectos personales o cuando utiliza un lenguaje de programación diferente. Los entornos de desarrollo son tan únicos como los desarrolladores que los utilizan.
|
||||
|
||||
### Editores
|
||||
|
||||
Una de las herramientas más cruciales para el desarrollo de software es el editor. Los editores son donde escribes tu código y, a veces, donde ejecutas tu código.
|
||||
|
||||
Los desarrolladores dependen de los editores por varias razones adicionales:
|
||||
|
||||
- *Depuración* ayuda a descubrir errores y fallos al analizar el código línea por línea. Algunos editores tienen capacidades de depuración; pueden ser personalizados y añadidos para lenguajes de programación específicos.
|
||||
- *Resaltado de sintaxis* agrega colores y formato de texto al código, haciéndolo más fácil de leer. La mayoría de los editores permiten personalizar el resaltado de sintaxis.
|
||||
- *Extensiones e Integraciones* son herramientas especializadas para desarrolladores, creadas por desarrolladores. Estas herramientas no están integradas en el editor base. Por ejemplo, muchos desarrolladores documentan su código para explicar cómo funciona. Pueden instalar una extensión de corrección ortográfica para ayudar a encontrar errores tipográficos en la documentación. La mayoría de las extensiones están destinadas a ser utilizadas dentro de un editor específico, y la mayoría de los editores vienen con una forma de buscar extensiones disponibles.
|
||||
- *Personalización* permite a los desarrolladores crear un entorno de desarrollo único que se adapte a sus necesidades. La mayoría de los editores son extremadamente personalizables y también pueden permitir a los desarrolladores crear extensiones personalizadas.
|
||||
|
||||
#### Editores Populares y Extensiones para Desarrollo Web
|
||||
|
||||
- [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker)
|
||||
- [Live Share](https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare)
|
||||
- [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
|
||||
- [Atom](https://atom.io/)
|
||||
- [spell-check](https://atom.io/packages/spell-check)
|
||||
- [teletype](https://atom.io/packages/teletype)
|
||||
- [atom-beautify](https://atom.io/packages/atom-beautify)
|
||||
|
||||
- [Sublimetext](https://www.sublimetext.com/)
|
||||
- [emmet](https://emmet.io/)
|
||||
- [SublimeLinter](http://www.sublimelinter.com/en/stable/)
|
||||
|
||||
### Navegadores
|
||||
|
||||
Otra herramienta crucial es el navegador. Los desarrolladores web dependen del navegador para ver cómo su código se ejecuta en la web. También se utiliza para mostrar los elementos visuales de una página web que se escriben en el editor, como HTML.
|
||||
|
||||
Muchos navegadores vienen con *herramientas para desarrolladores* (DevTools) que contienen un conjunto de características útiles e información para ayudar a los desarrolladores a recopilar y capturar información importante sobre su aplicación. Por ejemplo: Si una página web tiene errores, a veces es útil saber cuándo ocurrieron. Las DevTools en un navegador pueden configurarse para capturar esta información.
|
||||
|
||||
#### Navegadores Populares y DevTools
|
||||
|
||||
- [Edge](https://docs.microsoft.com/microsoft-edge/devtools-guide-chromium/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [Chrome](https://developers.google.com/web/tools/chrome-devtools/)
|
||||
- [Firefox](https://developer.mozilla.org/docs/Tools)
|
||||
|
||||
### Herramientas de Línea de Comandos
|
||||
|
||||
Algunos desarrolladores prefieren una vista menos gráfica para sus tareas diarias y dependen de la línea de comandos para lograrlo. Escribir código requiere una cantidad significativa de tipeo y algunos desarrolladores prefieren no interrumpir su flujo en el teclado. Utilizan atajos de teclado para cambiar entre ventanas del escritorio, trabajar en diferentes archivos y usar herramientas. La mayoría de las tareas se pueden completar con un mouse, pero una ventaja de usar la línea de comandos es que se puede hacer mucho con herramientas de línea de comandos sin necesidad de cambiar entre el mouse y el teclado. Otra ventaja de la línea de comandos es que son configurables y puedes guardar una configuración personalizada, cambiarla más tarde e importarla a otras máquinas de desarrollo. Debido a que los entornos de desarrollo son tan únicos para cada desarrollador, algunos evitarán usar la línea de comandos, otros dependerán completamente de ella y algunos preferirán una mezcla de ambos.
|
||||
|
||||
### Opciones Populares de Línea de Comandos
|
||||
|
||||
Las opciones para la línea de comandos diferirán según el sistema operativo que utilices.
|
||||
|
||||
*💻 = viene preinstalado en el sistema operativo.*
|
||||
|
||||
#### Windows
|
||||
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/overview?view=powershell-7/?WT.mc_id=academic-77807-sagibbon) 💻
|
||||
- [Command Line](https://docs.microsoft.com/windows-server/administration/windows-commands/windows-commands/?WT.mc_id=academic-77807-sagibbon) (también conocido como CMD) 💻
|
||||
- [Windows Terminal](https://docs.microsoft.com/windows/terminal/?WT.mc_id=academic-77807-sagibbon)
|
||||
- [mintty](https://mintty.github.io/)
|
||||
|
||||
#### MacOS
|
||||
|
||||
- [Terminal](https://support.apple.com/guide/terminal/open-or-quit-terminal-apd5265185d-f365-44cb-8b09-71a064a42125/mac) 💻
|
||||
- [iTerm](https://iterm2.com/)
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
|
||||
|
||||
#### Linux
|
||||
|
||||
- [Bash](https://www.gnu.org/software/bash/manual/html_node/index.html) 💻
|
||||
- [KDE Konsole](https://docs.kde.org/trunk5/en/konsole/konsole/index.html)
|
||||
- [Powershell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7/?WT.mc_id=academic-77807-sagibbon)
|
||||
|
||||
#### Herramientas Populares de Línea de Comandos
|
||||
|
||||
- [Git](https://git-scm.com/) (💻 en la mayoría de los sistemas operativos)
|
||||
- [NPM](https://www.npmjs.com/)
|
||||
- [Yarn](https://classic.yarnpkg.com/en/docs/cli/)
|
||||
|
||||
### Documentación
|
||||
|
||||
Cuando un desarrollador quiere aprender algo nuevo, probablemente recurrirá a la documentación para aprender cómo usarlo. Los desarrolladores suelen depender de la documentación para guiarlos sobre cómo usar herramientas y lenguajes correctamente, y también para obtener un conocimiento más profundo de cómo funcionan.
|
||||
|
||||
#### Documentación Popular sobre Desarrollo Web
|
||||
|
||||
- [Mozilla Developer Network (MDN)](https://developer.mozilla.org/docs/Web), de Mozilla, los editores del navegador [Firefox](https://www.mozilla.org/firefox/)
|
||||
- [Frontend Masters](https://frontendmasters.com/learn/)
|
||||
- [Web.dev](https://web.dev), de Google, editores de [Chrome](https://www.google.com/chrome/)
|
||||
- [Documentación para desarrolladores de Microsoft](https://docs.microsoft.com/microsoft-edge/#microsoft-edge-for-developers), para [Microsoft Edge](https://www.microsoft.com/edge)
|
||||
- [W3 Schools](https://www.w3schools.com/where_to_start.asp)
|
||||
|
||||
✅ Investiga: Ahora que conoces los conceptos básicos del entorno de un desarrollador web, compáralo con el entorno de un diseñador web.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Desafío
|
||||
|
||||
Compara algunos lenguajes de programación. ¿Cuáles son algunas de las características únicas de JavaScript frente a Java? ¿Qué hay de COBOL frente a Go?
|
||||
|
||||
## Cuestionario Posterior a la Clase
|
||||
[Cuestionario posterior a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/2)
|
||||
|
||||
## Revisión y Autoestudio
|
||||
|
||||
Estudia un poco sobre los diferentes lenguajes disponibles para el programador. Intenta escribir una línea en un lenguaje y luego reescribirla en otros dos. ¿Qué aprendiste?
|
||||
|
||||
## Tarea
|
||||
|
||||
[Leer la Documentación](assignment.md)
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "1ce4deaec80130d3a0a3c906568459fc",
|
||||
"translation_date": "2025-08-24T13:01:21+00:00",
|
||||
"source_file": "1-getting-started-lessons/1-intro-to-programming-languages/assignment.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Leyendo la Documentación
|
||||
|
||||
## Instrucciones
|
||||
|
||||
Existen muchas herramientas que un desarrollador web puede necesitar y que se encuentran en la [documentación de MDN sobre herramientas del lado del cliente](https://developer.mozilla.org/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview). Selecciona 3 herramientas que no se hayan cubierto en la lección, explica por qué un desarrollador web las usaría y busca una herramienta que pertenezca a esta categoría para compartir su documentación. No utilices el mismo ejemplo de herramienta que aparece en la documentación de MDN.
|
||||
|
||||
## Rúbrica
|
||||
|
||||
Ejemplar | Adecuado | Necesita Mejorar
|
||||
--- | --- | -- |
|
||||
|Explicó por qué un desarrollador web usaría la herramienta| Explicó cómo, pero no por qué un desarrollador usaría la herramienta| No mencionó cómo ni por qué un desarrollador usaría la herramienta |
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,337 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "05666cecb8983a72cf0ce1d18932b5b7",
|
||||
"translation_date": "2025-08-24T12:47:41+00:00",
|
||||
"source_file": "1-getting-started-lessons/2-github-basics/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Introducción a GitHub
|
||||
|
||||
Esta lección cubre los conceptos básicos de GitHub, una plataforma para alojar y gestionar cambios en tu código.
|
||||
|
||||

|
||||
> Sketchnote por [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Cuestionario previo a la lección
|
||||
[Cuestionario previo a la lección](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/3)
|
||||
|
||||
## Introducción
|
||||
|
||||
En esta lección, cubriremos:
|
||||
|
||||
- cómo rastrear el trabajo que haces en tu máquina
|
||||
- cómo trabajar en proyectos con otros
|
||||
- cómo contribuir al software de código abierto
|
||||
|
||||
### Prerrequisitos
|
||||
|
||||
Antes de comenzar, necesitas verificar si Git está instalado. En la terminal escribe:
|
||||
`git --version`
|
||||
|
||||
Si Git no está instalado, [descarga Git](https://git-scm.com/downloads). Luego, configura tu perfil local de Git en la terminal:
|
||||
* `git config --global user.name "tu-nombre"`
|
||||
* `git config --global user.email "tu-correo"`
|
||||
|
||||
Para verificar si Git ya está configurado, puedes escribir:
|
||||
`git config --list`
|
||||
|
||||
También necesitarás una cuenta de GitHub, un editor de código (como Visual Studio Code) y abrir tu terminal (o símbolo del sistema).
|
||||
|
||||
Navega a [github.com](https://github.com/) y crea una cuenta si aún no lo has hecho, o inicia sesión y completa tu perfil.
|
||||
|
||||
✅ GitHub no es el único repositorio de código en el mundo; hay otros, pero GitHub es el más conocido.
|
||||
|
||||
### Preparación
|
||||
|
||||
Necesitarás una carpeta con un proyecto de código en tu máquina local (laptop o PC) y un repositorio público en GitHub, que servirá como ejemplo de cómo contribuir a los proyectos de otros.
|
||||
|
||||
---
|
||||
|
||||
## Gestión de código
|
||||
|
||||
Supongamos que tienes una carpeta local con un proyecto de código y quieres comenzar a rastrear tu progreso usando git, el sistema de control de versiones. Algunas personas comparan usar git con escribir una carta de amor a tu futuro yo. Al leer tus mensajes de confirmación días, semanas o meses después, podrás recordar por qué tomaste una decisión o "revertir" un cambio, siempre y cuando escribas buenos "mensajes de confirmación".
|
||||
|
||||
### Tarea: Crear un repositorio y confirmar código
|
||||
|
||||
> Mira el video
|
||||
>
|
||||
> [](https://www.youtube.com/watch?v=9R31OUPpxU4)
|
||||
|
||||
1. **Crear un repositorio en GitHub**. En GitHub.com, en la pestaña de repositorios o desde la barra de navegación en la parte superior derecha, encuentra el botón **nuevo repositorio**.
|
||||
|
||||
1. Dale un nombre a tu repositorio (carpeta).
|
||||
1. Selecciona **crear repositorio**.
|
||||
|
||||
1. **Navega a tu carpeta de trabajo**. En tu terminal, cambia a la carpeta (también conocida como directorio) que deseas comenzar a rastrear. Escribe:
|
||||
|
||||
```bash
|
||||
cd [name of your folder]
|
||||
```
|
||||
|
||||
1. **Inicializa un repositorio de git**. En tu proyecto escribe:
|
||||
|
||||
```bash
|
||||
git init
|
||||
```
|
||||
|
||||
1. **Verifica el estado**. Para verificar el estado de tu repositorio escribe:
|
||||
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
|
||||
La salida puede verse algo así:
|
||||
|
||||
```output
|
||||
Changes not staged for commit:
|
||||
(use "git add <file>..." to update what will be committed)
|
||||
(use "git checkout -- <file>..." to discard changes in working directory)
|
||||
|
||||
modified: file.txt
|
||||
modified: file2.txt
|
||||
```
|
||||
|
||||
Normalmente, el comando `git status` te dice cosas como qué archivos están listos para ser _guardados_ en el repositorio o tienen cambios que podrías querer persistir.
|
||||
|
||||
1. **Agrega todos los archivos para rastrear**
|
||||
Esto también se llama preparar archivos/agregar archivos al área de preparación.
|
||||
|
||||
```bash
|
||||
git add .
|
||||
```
|
||||
|
||||
El argumento `git add` más `.` indica que todos tus archivos y cambios serán rastreados.
|
||||
|
||||
1. **Agrega archivos seleccionados para rastrear**
|
||||
|
||||
```bash
|
||||
git add [file or folder name]
|
||||
```
|
||||
|
||||
Esto nos ayuda a agregar solo archivos seleccionados al área de preparación cuando no queremos confirmar todos los archivos de una vez.
|
||||
|
||||
1. **Quitar la preparación de todos los archivos**
|
||||
|
||||
```bash
|
||||
git reset
|
||||
```
|
||||
|
||||
Este comando nos ayuda a quitar la preparación de todos los archivos de una vez.
|
||||
|
||||
1. **Quitar la preparación de un archivo en particular**
|
||||
|
||||
```bash
|
||||
git reset [file or folder name]
|
||||
```
|
||||
|
||||
Este comando nos ayuda a quitar la preparación de solo un archivo en particular que no queremos incluir en la próxima confirmación.
|
||||
|
||||
1. **Persistir tu trabajo**. En este punto, has agregado los archivos a un área llamada _área de preparación_. Un lugar donde Git está rastreando tus archivos. Para hacer el cambio permanente necesitas _confirmar_ los archivos. Para hacerlo, crea una _confirmación_ con el comando `git commit`. Una _confirmación_ representa un punto de guardado en la historia de tu repositorio. Escribe lo siguiente para crear una _confirmación_:
|
||||
|
||||
```bash
|
||||
git commit -m "first commit"
|
||||
```
|
||||
|
||||
Esto confirma todos tus archivos, agregando el mensaje "primer commit". Para futuros mensajes de confirmación, querrás ser más descriptivo en tu descripción para transmitir qué tipo de cambio has realizado.
|
||||
|
||||
1. **Conecta tu repositorio local de Git con GitHub**. Un repositorio de Git es útil en tu máquina, pero en algún momento querrás tener una copia de seguridad de tus archivos en algún lugar y también invitar a otras personas a trabajar contigo en tu repositorio. Un gran lugar para hacerlo es GitHub. Recuerda que ya hemos creado un repositorio en GitHub, así que lo único que necesitamos hacer es conectar nuestro repositorio local de Git con GitHub. El comando `git remote add` hará justo eso. Escribe el siguiente comando:
|
||||
|
||||
> Nota: antes de escribir el comando, ve a la página de tu repositorio en GitHub para encontrar la URL del repositorio. La usarás en el siguiente comando. Reemplaza ```https://github.com/username/repository_name.git``` con tu URL de GitHub.
|
||||
|
||||
```bash
|
||||
git remote add origin https://github.com/username/repository_name.git
|
||||
```
|
||||
|
||||
Esto crea una _remota_, o conexión, llamada "origin" que apunta al repositorio de GitHub que creaste anteriormente.
|
||||
|
||||
1. **Enviar archivos locales a GitHub**. Hasta ahora has creado una _conexión_ entre el repositorio local y el repositorio de GitHub. Enviemos estos archivos a GitHub con el siguiente comando `git push`, de esta manera:
|
||||
|
||||
> Nota: el nombre de tu rama puede ser diferente por defecto de ```main```.
|
||||
|
||||
```bash
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
Esto envía tus confirmaciones en tu rama "main" a GitHub.
|
||||
|
||||
2. **Para agregar más cambios**. Si deseas continuar haciendo cambios y enviándolos a GitHub, solo necesitarás usar los siguientes tres comandos:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "type your commit message here"
|
||||
git push
|
||||
```
|
||||
|
||||
> Consejo: También podrías querer adoptar un archivo `.gitignore` para evitar que los archivos que no deseas rastrear aparezcan en GitHub, como ese archivo de notas que guardas en la misma carpeta pero que no tiene lugar en un repositorio público. Puedes encontrar plantillas para archivos `.gitignore` en [.gitignore templates](https://github.com/github/gitignore).
|
||||
|
||||
#### Mensajes de confirmación
|
||||
|
||||
Un gran mensaje de confirmación de Git completa la siguiente oración:
|
||||
Si se aplica, esta confirmación <tu línea de asunto aquí>
|
||||
|
||||
Para el asunto, usa el tiempo presente e imperativo: "cambiar" en lugar de "cambiado" ni "cambios".
|
||||
Al igual que en el asunto, en el cuerpo (opcional) también usa el tiempo presente e imperativo. El cuerpo debe incluir la motivación para el cambio y contrastarlo con el comportamiento anterior. Estás explicando el `por qué`, no el `cómo`.
|
||||
|
||||
✅ Tómate unos minutos para navegar por GitHub. ¿Puedes encontrar un mensaje de confirmación realmente bueno? ¿Puedes encontrar uno realmente mínimo? ¿Qué información crees que es la más importante y útil para transmitir en un mensaje de confirmación?
|
||||
|
||||
### Tarea: Colaborar
|
||||
|
||||
La razón principal para poner cosas en GitHub es hacer posible colaborar con otros desarrolladores.
|
||||
|
||||
## Trabajar en proyectos con otros
|
||||
|
||||
> Mira el video
|
||||
>
|
||||
> [](https://www.youtube.com/watch?v=bFCM-PC3cu8)
|
||||
|
||||
En tu repositorio, navega a `Insights > Community` para ver cómo tu proyecto se compara con los estándares comunitarios recomendados.
|
||||
|
||||
Aquí hay algunas cosas que pueden mejorar tu repositorio de GitHub:
|
||||
- **Descripción**. ¿Agregaste una descripción para tu proyecto?
|
||||
- **README**. ¿Agregaste un README? GitHub proporciona orientación para escribir un [README](https://docs.github.com/articles/about-readmes/?WT.mc_id=academic-77807-sagibbon).
|
||||
- **Guía de contribución**. ¿Tu proyecto tiene [guías de contribución](https://docs.github.com/articles/setting-guidelines-for-repository-contributors/?WT.mc_id=academic-77807-sagibbon)?
|
||||
- **Código de conducta**. ¿Un [Código de Conducta](https://docs.github.com/articles/adding-a-code-of-conduct-to-your-project/)?
|
||||
- **Licencia**. Quizás lo más importante, una [licencia](https://docs.github.com/articles/adding-a-license-to-a-repository/)?
|
||||
|
||||
Todos estos recursos beneficiarán la incorporación de nuevos miembros al equipo. Y típicamente son el tipo de cosas que los nuevos contribuyentes miran antes de siquiera mirar tu código, para averiguar si tu proyecto es el lugar adecuado para que dediquen su tiempo.
|
||||
|
||||
✅ Los archivos README, aunque toman tiempo para prepararse, a menudo son descuidados por los mantenedores ocupados. ¿Puedes encontrar un ejemplo de uno particularmente descriptivo? Nota: hay algunos [herramientas para ayudar a crear buenos READMEs](https://www.makeareadme.com/) que podrías querer probar.
|
||||
|
||||
### Tarea: Fusionar código
|
||||
|
||||
Los documentos de contribución ayudan a las personas a contribuir al proyecto. Explican qué tipos de contribuciones estás buscando y cómo funciona el proceso. Los contribuyentes necesitarán pasar por una serie de pasos para poder contribuir a tu repositorio en GitHub:
|
||||
|
||||
1. **Hacer un fork de tu repositorio**. Probablemente querrás que las personas _hagan un fork_ de tu proyecto. Hacer un fork significa crear una réplica de tu repositorio en su perfil de GitHub.
|
||||
1. **Clonar**. Desde allí, clonarán el proyecto a su máquina local.
|
||||
1. **Crear una rama**. Querrás pedirles que creen una _rama_ para su trabajo.
|
||||
1. **Enfocar su cambio en un área**. Pide a los contribuyentes que concentren sus contribuciones en una sola cosa a la vez; de esa manera, las posibilidades de que puedas _fusionar_ su trabajo son mayores. Imagina que escriben una corrección de errores, agregan una nueva funcionalidad y actualizan varias pruebas; ¿qué pasa si quieres, o solo puedes implementar 2 de 3, o 1 de 3 cambios?
|
||||
|
||||
✅ Imagina una situación donde las ramas son particularmente críticas para escribir y enviar buen código. ¿Qué casos de uso puedes pensar?
|
||||
|
||||
> Nota: sé el cambio que quieres ver en el mundo y crea ramas para tu propio trabajo también. Cualquier confirmación que hagas se realizará en la rama en la que estés "revisado". Usa `git status` para ver en qué rama estás.
|
||||
|
||||
Pasemos por un flujo de trabajo de contribuyente. Supongamos que el contribuyente ya ha _hecho un fork_ y _clonado_ el repositorio, por lo que tiene un repositorio de Git listo para trabajar en su máquina local:
|
||||
|
||||
1. **Crear una rama**. Usa el comando `git branch` para crear una rama que contendrá los cambios que planean contribuir:
|
||||
|
||||
```bash
|
||||
git branch [branch-name]
|
||||
```
|
||||
|
||||
1. **Cambiar a la rama de trabajo**. Cambia a la rama especificada y actualiza el directorio de trabajo con `git switch`:
|
||||
|
||||
```bash
|
||||
git switch [branch-name]
|
||||
```
|
||||
|
||||
1. **Hacer el trabajo**. En este punto, quieres agregar tus cambios. No olvides informarle a Git con los siguientes comandos:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "my changes"
|
||||
```
|
||||
|
||||
Asegúrate de darle un buen nombre a tu confirmación, tanto para tu beneficio como para el mantenedor del repositorio al que estás ayudando.
|
||||
|
||||
1. **Combinar tu trabajo con la rama `main`**. En algún momento habrás terminado de trabajar y querrás combinar tu trabajo con el de la rama `main`. La rama `main` podría haber cambiado mientras tanto, así que asegúrate de actualizarla primero con los siguientes comandos:
|
||||
|
||||
```bash
|
||||
git switch main
|
||||
git pull
|
||||
```
|
||||
|
||||
En este punto, asegúrate de que cualquier _conflicto_, situaciones donde Git no puede fácilmente _combinar_ los cambios, ocurra en tu rama de trabajo. Por lo tanto, ejecuta los siguientes comandos:
|
||||
|
||||
```bash
|
||||
git switch [branch_name]
|
||||
git merge main
|
||||
```
|
||||
|
||||
Esto traerá todos los cambios de `main` a tu rama y, con suerte, podrás continuar. Si no, VS Code te indicará dónde Git está _confundido_ y solo tendrás que alterar los archivos afectados para indicar qué contenido es el más preciso.
|
||||
|
||||
1. **Enviar tu trabajo a GitHub**. Enviar tu trabajo a GitHub significa dos cosas: empujar tu rama a tu repositorio y luego abrir un PR (Pull Request).
|
||||
|
||||
```bash
|
||||
git push --set-upstream origin [branch-name]
|
||||
```
|
||||
|
||||
El comando anterior crea la rama en tu repositorio bifurcado.
|
||||
|
||||
1. **Abrir un PR**. A continuación, querrás abrir un PR. Hazlo navegando al repositorio bifurcado en GitHub. Verás una indicación en GitHub donde te pregunta si deseas crear un nuevo PR; haz clic en eso y serás llevado a una interfaz donde puedes cambiar el título del mensaje de confirmación, darle una descripción más adecuada. Ahora el mantenedor del repositorio que bifurcaste verá este PR y _crucemos los dedos_ apreciará y _fusionará_ tu PR. Ahora eres un contribuyente, ¡yay! :)
|
||||
|
||||
1. **Limpiar**. Se considera una buena práctica _limpiar_ después de fusionar exitosamente un PR. Querrás limpiar tanto tu rama local como la rama que empujaste a GitHub. Primero eliminémosla localmente con el siguiente comando:
|
||||
|
||||
```bash
|
||||
git branch -d [branch-name]
|
||||
```
|
||||
Asegúrate de ir a la página de GitHub del repositorio bifurcado a continuación y eliminar la rama remota que acabas de subir.
|
||||
|
||||
`Pull request` parece un término un poco extraño porque en realidad quieres enviar tus cambios al proyecto. Pero el mantenedor (propietario del proyecto) o el equipo principal necesita considerar tus cambios antes de fusionarlos con la rama "principal" del proyecto, por lo que en realidad estás solicitando una decisión de cambio a un mantenedor.
|
||||
|
||||
Un pull request es el lugar donde se comparan y discuten las diferencias introducidas en una rama con revisiones, comentarios, pruebas integradas y más. Un buen pull request sigue aproximadamente las mismas reglas que un mensaje de commit. Puedes agregar una referencia a un problema en el rastreador de problemas, por ejemplo, cuando tu trabajo soluciona un problema. Esto se hace usando un `#` seguido del número de tu problema. Por ejemplo, `#97`.
|
||||
|
||||
🤞Crucemos los dedos para que todas las verificaciones pasen y el/los propietario(s) del proyecto fusionen tus cambios en el proyecto🤞
|
||||
|
||||
Actualiza tu rama de trabajo local actual con todos los nuevos commits de la rama remota correspondiente en GitHub:
|
||||
|
||||
`git pull`
|
||||
|
||||
## Cómo contribuir a código abierto
|
||||
|
||||
Primero, busquemos un repositorio (o **repo**) en GitHub que te interese y al que te gustaría contribuir con un cambio. Querrás copiar su contenido a tu máquina.
|
||||
|
||||
✅ Una buena forma de encontrar repositorios 'amigables para principiantes' es [buscar por la etiqueta 'good-first-issue'](https://github.blog/2020-01-22-browse-good-first-issues-to-start-contributing-to-open-source/).
|
||||
|
||||

|
||||
|
||||
Hay varias formas de copiar código. Una forma es "clonar" el contenido del repositorio, usando HTTPS, SSH o la CLI (Interfaz de Línea de Comandos) de GitHub.
|
||||
|
||||
Abre tu terminal y clona el repositorio de esta manera:
|
||||
`git clone https://github.com/ProjectURL`
|
||||
|
||||
Para trabajar en el proyecto, cambia al directorio correcto:
|
||||
`cd ProjectURL`
|
||||
|
||||
También puedes abrir el proyecto completo usando [Codespaces](https://github.com/features/codespaces), el editor de código integrado / entorno de desarrollo en la nube de GitHub, o [GitHub Desktop](https://desktop.github.com/).
|
||||
|
||||
Por último, puedes descargar el código en una carpeta comprimida.
|
||||
|
||||
### Algunas cosas interesantes sobre GitHub
|
||||
|
||||
Puedes marcar con estrella, observar y/o "bifurcar" cualquier repositorio público en GitHub. Puedes encontrar tus repositorios marcados con estrella en el menú desplegable de la esquina superior derecha. Es como guardar en favoritos, pero para código.
|
||||
|
||||
Los proyectos tienen un rastreador de problemas, generalmente en GitHub en la pestaña "Issues" a menos que se indique lo contrario, donde las personas discuten problemas relacionados con el proyecto. Y la pestaña de Pull Requests es donde las personas discuten y revisan los cambios que están en progreso.
|
||||
|
||||
Los proyectos también pueden tener discusiones en foros, listas de correo o canales de chat como Slack, Discord o IRC.
|
||||
|
||||
✅ Echa un vistazo a tu nuevo repositorio de GitHub y prueba algunas cosas, como editar configuraciones, agregar información a tu repositorio y crear un proyecto (como un tablero Kanban). ¡Hay mucho que puedes hacer!
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Desafío
|
||||
|
||||
Trabaja en pareja con un amigo para trabajar en el código del otro. Crea un proyecto de manera colaborativa, bifurca código, crea ramas y fusiona cambios.
|
||||
|
||||
## Cuestionario posterior a la clase
|
||||
[Cuestionario posterior a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/4)
|
||||
|
||||
## Revisión y autoestudio
|
||||
|
||||
Lee más sobre [cómo contribuir a software de código abierto](https://opensource.guide/how-to-contribute/#how-to-submit-a-contribution).
|
||||
|
||||
[Hoja de referencia de Git](https://training.github.com/downloads/github-git-cheat-sheet/).
|
||||
|
||||
Practica, practica, practica. GitHub tiene excelentes rutas de aprendizaje disponibles en [skills.github.com](https://skills.github.com):
|
||||
|
||||
- [Primera semana en GitHub](https://skills.github.com/#first-week-on-github)
|
||||
|
||||
También encontrarás cursos más avanzados.
|
||||
|
||||
## Tarea
|
||||
|
||||
Completa [el curso de la Primera Semana en GitHub](https://skills.github.com/#first-week-on-github).
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,242 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "e4cd5b1faed4adab5acf720f82798003",
|
||||
"translation_date": "2025-08-24T12:52:54+00:00",
|
||||
"source_file": "1-getting-started-lessons/3-accessibility/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Creando Páginas Web Accesibles
|
||||
|
||||

|
||||
> Sketchnote por [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Cuestionario Previo a la Clase
|
||||
[Cuestionario previo a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/5)
|
||||
|
||||
> El poder de la Web está en su universalidad. El acceso para todos, independientemente de la discapacidad, es un aspecto esencial.
|
||||
>
|
||||
> \- Sir Timothy Berners-Lee, Director de W3C e inventor de la World Wide Web
|
||||
|
||||
Esta cita destaca perfectamente la importancia de crear sitios web accesibles. Una aplicación que no puede ser utilizada por todos es, por definición, excluyente. Como desarrolladores web, siempre debemos tener en mente la accesibilidad. Al enfocarnos en esto desde el principio, estaremos en el camino correcto para garantizar que todos puedan acceder a las páginas que creamos. En esta lección, aprenderás sobre las herramientas que pueden ayudarte a garantizar que tus recursos web sean accesibles y cómo construir con la accesibilidad en mente.
|
||||
|
||||
> ¡Puedes tomar esta lección en [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101/accessibility/?WT.mc_id=academic-77807-sagibbon)!
|
||||
|
||||
## Herramientas para usar
|
||||
|
||||
### Lectores de pantalla
|
||||
|
||||
Una de las herramientas de accesibilidad más conocidas son los lectores de pantalla.
|
||||
|
||||
[Lectores de pantalla](https://en.wikipedia.org/wiki/Screen_reader) son clientes comúnmente utilizados por personas con discapacidades visuales. Así como dedicamos tiempo a garantizar que un navegador transmita correctamente la información que queremos compartir, también debemos asegurarnos de que un lector de pantalla haga lo mismo.
|
||||
|
||||
En su forma más básica, un lector de pantalla leerá una página de arriba hacia abajo de forma audible. Si tu página es solo texto, el lector transmitirá la información de manera similar a un navegador. Por supuesto, las páginas web rara vez son puramente texto; contienen enlaces, gráficos, colores y otros componentes visuales. Se debe tener cuidado para garantizar que esta información se lea correctamente por un lector de pantalla.
|
||||
|
||||
Todo desarrollador web debería familiarizarse con un lector de pantalla. Como se destacó anteriormente, es el cliente que tus usuarios utilizarán. De la misma manera que estás familiarizado con cómo opera un navegador, deberías aprender cómo opera un lector de pantalla. Afortunadamente, los lectores de pantalla están integrados en la mayoría de los sistemas operativos.
|
||||
|
||||
Algunos navegadores también tienen herramientas integradas y extensiones que pueden leer texto en voz alta o incluso proporcionar algunas funciones básicas de navegación, como [estas herramientas enfocadas en accesibilidad del navegador Edge](https://support.microsoft.com/help/4000734/microsoft-edge-accessibility-features). Estas también son herramientas importantes de accesibilidad, pero funcionan de manera muy diferente a los lectores de pantalla y no deben confundirse con herramientas de prueba de lectores de pantalla.
|
||||
|
||||
✅ Prueba un lector de pantalla y un lector de texto del navegador. En Windows, [Narrador](https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1/?WT.mc_id=academic-77807-sagibbon) está incluido por defecto, y [JAWS](https://webaim.org/articles/jaws/) y [NVDA](https://www.nvaccess.org/about-nvda/) también se pueden instalar. En macOS y iOS, [VoiceOver](https://support.apple.com/guide/voiceover/welcome/10) está instalado por defecto.
|
||||
|
||||
### Zoom
|
||||
|
||||
Otra herramienta comúnmente utilizada por personas con discapacidades visuales es el zoom. El tipo más básico de zoom es el zoom estático, controlado mediante `Control + signo más (+)` o disminuyendo la resolución de la pantalla. Este tipo de zoom hace que toda la página cambie de tamaño, por lo que usar [diseño responsivo](https://developer.mozilla.org/docs/Learn/CSS/CSS_layout/Responsive_Design) es importante para proporcionar una buena experiencia de usuario en niveles de zoom aumentados.
|
||||
|
||||
Otro tipo de zoom depende de software especializado para ampliar un área de la pantalla y desplazarse, como usar una lupa real. En Windows, [Lupa](https://support.microsoft.com/windows/use-magnifier-to-make-things-on-the-screen-easier-to-see-414948ba-8b1c-d3bd-8615-0e5e32204198) está integrado, y [ZoomText](https://www.freedomscientific.com/training/zoomtext/getting-started/) es un software de ampliación de terceros con más funciones y una base de usuarios más grande. Tanto macOS como iOS tienen un software de ampliación integrado llamado [Zoom](https://www.apple.com/accessibility/mac/vision/).
|
||||
|
||||
### Comprobadores de contraste
|
||||
|
||||
Los colores en los sitios web deben elegirse cuidadosamente para responder a las necesidades de los usuarios con daltonismo o personas que tienen dificultades para ver colores de bajo contraste.
|
||||
|
||||
✅ Prueba un sitio web que disfrutes usando para verificar el uso de colores con una extensión de navegador como [el comprobador de contraste de color de WCAG](https://microsoftedge.microsoft.com/addons/detail/wcag-color-contrast-check/idahaggnlnekelhgplklhfpchbfdmkjp?hl=en-US&WT.mc_id=academic-77807-sagibbon). ¿Qué aprendes?
|
||||
|
||||
### Lighthouse
|
||||
|
||||
En el área de herramientas para desarrolladores de tu navegador, encontrarás la herramienta Lighthouse. Esta herramienta es importante para obtener una primera vista de la accesibilidad (así como otros análisis) de un sitio web. Aunque es importante no depender exclusivamente de Lighthouse, una puntuación del 100% es muy útil como punto de partida.
|
||||
|
||||
✅ Encuentra Lighthouse en el panel de herramientas para desarrolladores de tu navegador y realiza un análisis en cualquier sitio. ¿Qué descubres?
|
||||
|
||||
## Diseñando para la accesibilidad
|
||||
|
||||
La accesibilidad es un tema relativamente amplio. Para ayudarte, hay numerosos recursos disponibles.
|
||||
|
||||
- [Accessible U - Universidad de Minnesota](https://accessibility.umn.edu/your-role/web-developers)
|
||||
|
||||
Aunque no podremos cubrir todos los aspectos de la creación de sitios accesibles, a continuación se presentan algunos de los principios básicos que querrás implementar. Diseñar una página accesible desde el principio es **siempre** más fácil que volver a una página existente para hacerla accesible.
|
||||
|
||||
## Buenos principios de diseño
|
||||
|
||||
### Paletas de colores seguras
|
||||
|
||||
Las personas ven el mundo de diferentes maneras, y esto incluye los colores. Al seleccionar un esquema de colores para tu sitio, debes asegurarte de que sea accesible para todos. Una excelente [herramienta para generar paletas de colores es Color Safe](http://colorsafe.co/).
|
||||
|
||||
✅ Identifica un sitio web que sea muy problemático en su uso de colores. ¿Por qué?
|
||||
|
||||
### Usa el HTML correcto
|
||||
|
||||
Con CSS y JavaScript es posible hacer que cualquier elemento parezca cualquier tipo de control. `<span>` podría usarse para crear un `<button>`, y `<b>` podría convertirse en un hipervínculo. Aunque esto podría considerarse más fácil de estilizar, no transmite nada a un lector de pantalla. Usa el HTML apropiado al crear controles en una página. Si quieres un hipervínculo, usa `<a>`. Usar el HTML correcto para el control correcto se llama hacer uso de HTML semántico.
|
||||
|
||||
✅ Ve a cualquier sitio web y verifica si los diseñadores y desarrolladores están usando HTML correctamente. ¿Puedes encontrar un botón que debería ser un enlace? Pista: haz clic derecho y elige 'Ver código fuente de la página' en tu navegador para mirar el código subyacente.
|
||||
|
||||
### Crea una jerarquía de encabezados descriptiva
|
||||
|
||||
Los usuarios de lectores de pantalla [dependen en gran medida de los encabezados](https://webaim.org/projects/screenreadersurvey8/#finding) para encontrar información y navegar por una página. Escribir contenido descriptivo en los encabezados y usar etiquetas semánticas de encabezados es importante para crear un sitio fácilmente navegable para los usuarios de lectores de pantalla.
|
||||
|
||||
### Usa buenas pistas visuales
|
||||
|
||||
CSS ofrece control total sobre el aspecto de cualquier elemento en una página. Puedes crear cuadros de texto sin un contorno o hipervínculos sin un subrayado. Desafortunadamente, eliminar esas pistas puede dificultar que alguien que depende de ellas pueda reconocer el tipo de control.
|
||||
|
||||
## La importancia del texto de los enlaces
|
||||
|
||||
Los hipervínculos son fundamentales para navegar por la web. Por lo tanto, garantizar que un lector de pantalla pueda leer correctamente los enlaces permite que todos los usuarios naveguen por tu sitio.
|
||||
|
||||
### Lectores de pantalla y enlaces
|
||||
|
||||
Como cabría esperar, los lectores de pantalla leen el texto de los enlaces de la misma manera que leerían cualquier otro texto en la página. Con esto en mente, el texto mostrado a continuación podría parecer perfectamente aceptable.
|
||||
|
||||
> El pingüino pequeño, a veces conocido como el pingüino hada, es el pingüino más pequeño del mundo. [Haz clic aquí](https://en.wikipedia.org/wiki/Little_penguin) para más información.
|
||||
|
||||
> El pingüino pequeño, a veces conocido como el pingüino hada, es el pingüino más pequeño del mundo. Visita https://en.wikipedia.org/wiki/Little_penguin para más información.
|
||||
|
||||
> **NOTE** Como estás a punto de leer, **nunca** deberías crear enlaces que se vean como los anteriores.
|
||||
|
||||
Recuerda, los lectores de pantalla son una interfaz diferente a los navegadores con un conjunto diferente de características.
|
||||
|
||||
### El problema de usar la URL
|
||||
|
||||
Los lectores de pantalla leen el texto. Si una URL aparece en el texto, el lector de pantalla leerá la URL. En general, la URL no transmite información significativa y puede sonar molesta. Es posible que hayas experimentado esto si tu teléfono alguna vez ha leído en voz alta un mensaje de texto con una URL.
|
||||
|
||||
### El problema de "haz clic aquí"
|
||||
|
||||
Los lectores de pantalla también tienen la capacidad de leer solo los hipervínculos en una página, de manera similar a como una persona con visión escanea una página en busca de enlaces. Si el texto del enlace siempre es "haz clic aquí", todo lo que el usuario escuchará será "haz clic aquí, haz clic aquí, haz clic aquí, haz clic aquí, haz clic aquí, ...". Todos los enlaces ahora son indistinguibles entre sí.
|
||||
|
||||
### Buen texto de enlace
|
||||
|
||||
Un buen texto de enlace describe brevemente lo que hay al otro lado del enlace. En el ejemplo anterior sobre los pingüinos pequeños, el enlace es a la página de Wikipedia sobre la especie. La frase *pingüinos pequeños* sería un texto de enlace perfecto, ya que deja claro qué aprenderá alguien si hace clic en el enlace: pingüinos pequeños.
|
||||
|
||||
> El [pingüino pequeño](https://en.wikipedia.org/wiki/Little_penguin), a veces conocido como el pingüino hada, es el pingüino más pequeño del mundo.
|
||||
|
||||
✅ Navega por la web durante unos minutos para encontrar páginas que usen estrategias de enlace poco claras. Compáralas con otros sitios que tengan mejores enlaces. ¿Qué aprendes?
|
||||
|
||||
#### Notas sobre motores de búsqueda
|
||||
|
||||
Como beneficio adicional por garantizar que tu sitio sea accesible para todos, también ayudarás a los motores de búsqueda a navegar por tu sitio. Los motores de búsqueda usan el texto de los enlaces para aprender los temas de las páginas. Así que usar buen texto de enlace ayuda a todos.
|
||||
|
||||
### ARIA
|
||||
|
||||
Imagina la siguiente página:
|
||||
|
||||
| Producto | Descripción | Ordenar |
|
||||
| ------------ | ------------------ | ------------ |
|
||||
| Widget | [Descripción](../../../../1-getting-started-lessons/3-accessibility/') | [Ordenar](../../../../1-getting-started-lessons/3-accessibility/') |
|
||||
| Súper widget | [Descripción](../../../../1-getting-started-lessons/3-accessibility/') | [Ordenar](../../../../1-getting-started-lessons/3-accessibility/') |
|
||||
|
||||
En este ejemplo, duplicar el texto de descripción y ordenar tiene sentido para alguien que usa un navegador. Sin embargo, alguien que usa un lector de pantalla solo escucharía las palabras *descripción* y *ordenar* repetidas sin contexto.
|
||||
|
||||
Para apoyar este tipo de escenarios, HTML admite un conjunto de atributos conocidos como [Aplicaciones Ricas de Internet Accesibles (ARIA)](https://developer.mozilla.org/docs/Web/Accessibility/ARIA). Estos atributos te permiten proporcionar información adicional a los lectores de pantalla.
|
||||
|
||||
> **NOTE**: Como muchos aspectos de HTML, el soporte de navegadores y lectores de pantalla puede variar. Sin embargo, la mayoría de los clientes principales admiten atributos ARIA.
|
||||
|
||||
Puedes usar `aria-label` para describir el enlace cuando el formato de la página no lo permite. La descripción para widget podría configurarse como
|
||||
|
||||
``` html
|
||||
<a href="#" aria-label="Widget description">description</a>
|
||||
```
|
||||
|
||||
✅ En general, usar marcado semántico como se describe anteriormente supera el uso de ARIA, pero a veces no hay un equivalente semántico para varios widgets HTML. Un buen ejemplo es un árbol. No hay un equivalente HTML para un árbol, por lo que identificas el `<div>` genérico para este elemento con un rol y valores ARIA adecuados. La [documentación de MDN sobre ARIA](https://developer.mozilla.org/docs/Web/Accessibility/ARIA) contiene más información útil.
|
||||
|
||||
```html
|
||||
<h2 id="tree-label">File Viewer</h2>
|
||||
<div role="tree" aria-labelledby="tree-label">
|
||||
<div role="treeitem" aria-expanded="false" tabindex="0">Uploads</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Imágenes
|
||||
|
||||
Es evidente que los lectores de pantalla no pueden leer automáticamente lo que hay en una imagen. Garantizar que las imágenes sean accesibles no requiere mucho trabajo: para eso sirve el atributo `alt`. Todas las imágenes significativas deben tener un `alt` para describir lo que son.
|
||||
Las imágenes que son puramente decorativas deben tener su atributo `alt` configurado como una cadena vacía: `alt=""`. Esto evita que los lectores de pantalla anuncien innecesariamente la imagen decorativa.
|
||||
|
||||
✅ Como era de esperar, los motores de búsqueda tampoco pueden entender lo que hay en una imagen. También usan texto alternativo. Así que, una vez más, garantizar que tu página sea accesible proporciona beneficios adicionales.
|
||||
|
||||
## El teclado
|
||||
|
||||
Algunos usuarios no pueden usar un ratón o trackpad, y dependen de interacciones con el teclado para moverse de un elemento a otro. Es importante que tu sitio web presente tu contenido en un orden lógico para que un usuario de teclado pueda acceder a cada elemento interactivo mientras avanza por un documento. Si construyes tus páginas web con marcado semántico y usas CSS para estilizar su diseño visual, tu sitio debería ser navegable con teclado, pero es importante probar este aspecto manualmente. Aprende más sobre [estrategias de navegación con teclado](https://webaim.org/techniques/keyboard/).
|
||||
|
||||
✅ Ve a cualquier sitio web e intenta navegar por él usando solo tu teclado. ¿Qué funciona, qué no funciona? ¿Por qué?
|
||||
|
||||
## Resumen
|
||||
|
||||
Una web accesible para algunos no es una verdadera 'world-wide web'. La mejor manera de garantizar que los sitios que creas sean accesibles es incorporar las mejores prácticas de accesibilidad desde el principio. Aunque hay pasos adicionales involucrados, incorporar estas habilidades en tu flujo de trabajo ahora significará que todas las páginas que crees serán accesibles.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Desafío
|
||||
|
||||
Toma este HTML y reescríbelo para que sea lo más accesible posible, dadas las estrategias que aprendiste.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
Example
|
||||
</title>
|
||||
<link href='../assets/style.css' rel='stylesheet' type='text/css'>
|
||||
</head>
|
||||
<body>
|
||||
<div class="site-header">
|
||||
<p class="site-title">Turtle Ipsum</p>
|
||||
<p class="site-subtitle">The World's Premier Turtle Fan Club</p>
|
||||
</div>
|
||||
<div class="main-nav">
|
||||
<p class="nav-header">Resources</p>
|
||||
<div class="nav-list">
|
||||
<p class="nav-item nav-item-bull"><a href="https://www.youtube.com/watch?v=CMNry4PE93Y">"I like turtles"</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="https://en.wikipedia.org/wiki/Turtle">Basic Turtle Info</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="https://en.wikipedia.org/wiki/Turtles_(chocolate)">Chocolate Turtles</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-content">
|
||||
<div>
|
||||
<p class="page-title">Welcome to Turtle Ipsum.
|
||||
<a href="">Click here</a> to learn more.
|
||||
</p>
|
||||
<p class="article-text">
|
||||
Turtle ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="footer-section">
|
||||
<span class="button">Sign up for turtle news</span>
|
||||
</div><div class="footer-section">
|
||||
<p class="nav-header footer-title">
|
||||
Internal Pages
|
||||
</p>
|
||||
<div class="nav-list">
|
||||
<p class="nav-item nav-item-bull"><a href="../">Index</a></p>
|
||||
<p class="nav-item nav-item-bull"><a href="../semantic">Semantic Example</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="footer-copyright">© 2016 Instrument</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Cuestionario Posterior a la Clase
|
||||
[Cuestionario posterior a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/6)
|
||||
|
||||
## Revisión y Autoestudio
|
||||
Muchos gobiernos tienen leyes relacionadas con los requisitos de accesibilidad. Investiga las leyes de accesibilidad de tu país. ¿Qué está cubierto y qué no? Un ejemplo es [este sitio web gubernamental](https://accessibility.blog.gov.uk/).
|
||||
|
||||
## Tarea
|
||||
|
||||
[Analiza un sitio web no accesible](assignment.md)
|
||||
|
||||
Créditos: [Turtle Ipsum](https://github.com/Instrument/semantic-html-sample) por Instrument
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "a258597a194e77d4fd469b3cd976b29e",
|
||||
"translation_date": "2025-08-24T12:57:02+00:00",
|
||||
"source_file": "1-getting-started-lessons/3-accessibility/assignment.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Analizar un sitio inaccesible
|
||||
|
||||
## Instrucciones
|
||||
|
||||
Identifica un sitio web que consideres NO accesible y crea un plan de acción para mejorar su accesibilidad.
|
||||
Tu primera tarea será identificar este sitio, detallar las formas en que crees que es inaccesible sin usar herramientas analíticas, y luego someterlo a un análisis de Lighthouse. Captura un pdf con los resultados de este análisis y elabora un plan detallado con un mínimo de diez puntos que muestren cómo se podría mejorar el sitio.
|
||||
|
||||
## Tabla para evaluar la accesibilidad del sitio
|
||||
|
||||
| Criterios | Ejemplar | Adecuado | Necesita Mejorar |
|
||||
|-----------|----------|----------|------------------|
|
||||
| | falta <10% de lo requerido | falta 20% de lo requerido | falta 50% de lo requerido |
|
||||
|
||||
----
|
||||
Informe del estudiante: incluye párrafos sobre cuán inaccesible es el sitio, el informe de Lighthouse capturado en pdf, una lista de diez puntos para mejorar, con detalles sobre cómo mejorarlo
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,29 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "04683f4cfa46004179b0404b89a3065c",
|
||||
"translation_date": "2025-08-24T12:46:16+00:00",
|
||||
"source_file": "1-getting-started-lessons/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Introducción al Desarrollo Web
|
||||
|
||||
En esta sección del currículo, se te presentarán conceptos importantes que no están basados en proyectos, pero que son esenciales para convertirte en un desarrollador profesional.
|
||||
|
||||
### Temas
|
||||
|
||||
1. [Introducción a los Lenguajes de Programación y Herramientas del Oficio](1-intro-to-programming-languages/README.md)
|
||||
2. [Introducción a GitHub](2-github-basics/README.md)
|
||||
3. [Fundamentos de Accesibilidad](3-accessibility/README.md)
|
||||
|
||||
### Créditos
|
||||
|
||||
Introducción a los Lenguajes de Programación y Herramientas del Oficio fue escrito con ♥️ por [Jasmine Greenaway](https://twitter.com/paladique)
|
||||
|
||||
Introducción a GitHub fue escrito con ♥️ por [Floor Drees](https://twitter.com/floordrees)
|
||||
|
||||
Fundamentos de Accesibilidad fue escrito con ♥️ por [Christopher Harrison](https://twitter.com/geektrainer)
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,213 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "fc6aef8ecfdd5b0ad2afa6e6ba52bfde",
|
||||
"translation_date": "2025-08-24T12:21:36+00:00",
|
||||
"source_file": "2-js-basics/1-data-types/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Conceptos Básicos de JavaScript: Tipos de Datos
|
||||
|
||||

|
||||
> Sketchnote por [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Cuestionario Previo a la Clase
|
||||
[Cuestionario previo a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/7)
|
||||
|
||||
Esta lección cubre los conceptos básicos de JavaScript, el lenguaje que proporciona interactividad en la web.
|
||||
|
||||
> Puedes tomar esta lección en [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-variables/?WT.mc_id=academic-77807-sagibbon)!
|
||||
|
||||
[](https://youtube.com/watch?v=JNIXfGiDWM8 "Variables en JavaScript")
|
||||
|
||||
[](https://youtube.com/watch?v=AWfA95eLdq8 "Tipos de Datos en JavaScript")
|
||||
|
||||
> 🎥 Haz clic en las imágenes de arriba para ver videos sobre variables y tipos de datos.
|
||||
|
||||
¡Comencemos con las variables y los tipos de datos que las llenan!
|
||||
|
||||
## Variables
|
||||
|
||||
Las variables almacenan valores que pueden ser utilizados y modificados a lo largo de tu código.
|
||||
|
||||
Crear y **declarar** una variable tiene la siguiente sintaxis **[palabra clave] [nombre]**. Está compuesta por dos partes:
|
||||
|
||||
- **Palabra clave**. Las palabras clave pueden ser `let` o `var`.
|
||||
|
||||
✅ La palabra clave `let` fue introducida en ES6 y le da a tu variable un llamado _alcance de bloque_. Se recomienda usar `let` en lugar de `var`. Cubriremos los alcances de bloque más a fondo en partes futuras.
|
||||
- **El nombre de la variable**, este es un nombre que eliges tú mismo.
|
||||
|
||||
### Tarea - Trabajando con Variables
|
||||
|
||||
1. **Declara una variable**. Declaremos una variable usando la palabra clave `let`:
|
||||
|
||||
```javascript
|
||||
let myVariable;
|
||||
```
|
||||
|
||||
`myVariable` ha sido declarada usando la palabra clave `let`. Actualmente no tiene un valor.
|
||||
|
||||
1. **Asigna un valor**. Almacena un valor en una variable con el operador `=`, seguido del valor esperado.
|
||||
|
||||
```javascript
|
||||
myVariable = 123;
|
||||
```
|
||||
|
||||
> Nota: el uso de `=` en esta lección significa que estamos utilizando un "operador de asignación", usado para establecer un valor a una variable. No denota igualdad.
|
||||
|
||||
`myVariable` ahora ha sido *inicializada* con el valor 123.
|
||||
|
||||
1. **Refactoriza**. Reemplaza tu código con la siguiente declaración.
|
||||
|
||||
```javascript
|
||||
let myVariable = 123;
|
||||
```
|
||||
|
||||
Lo anterior se llama una _inicialización explícita_ cuando una variable es declarada y se le asigna un valor al mismo tiempo.
|
||||
|
||||
1. **Cambia el valor de la variable**. Cambia el valor de la variable de la siguiente manera:
|
||||
|
||||
```javascript
|
||||
myVariable = 321;
|
||||
```
|
||||
|
||||
Una vez que una variable es declarada, puedes cambiar su valor en cualquier momento en tu código con el operador `=` y el nuevo valor.
|
||||
|
||||
✅ ¡Pruébalo! Puedes escribir JavaScript directamente en tu navegador. Abre una ventana del navegador y navega a las Herramientas de Desarrollador. En la consola, encontrarás un prompt; escribe `let myVariable = 123`, presiona enter, luego escribe `myVariable`. ¿Qué sucede? Nota, aprenderás más sobre estos conceptos en lecciones posteriores.
|
||||
|
||||
## Constantes
|
||||
|
||||
La declaración e inicialización de una constante sigue los mismos conceptos que una variable, con la excepción de la palabra clave `const`. Las constantes suelen declararse con letras mayúsculas.
|
||||
|
||||
```javascript
|
||||
const MY_VARIABLE = 123;
|
||||
```
|
||||
|
||||
Las constantes son similares a las variables, con dos excepciones:
|
||||
|
||||
- **Debe tener un valor**. Las constantes deben ser inicializadas, o se producirá un error al ejecutar el código.
|
||||
- **La referencia no puede cambiarse**. La referencia de una constante no puede cambiarse una vez inicializada, o se producirá un error al ejecutar el código. Veamos dos ejemplos:
|
||||
- **Valor simple**. Lo siguiente NO está permitido:
|
||||
|
||||
```javascript
|
||||
const PI = 3;
|
||||
PI = 4; // not allowed
|
||||
```
|
||||
|
||||
- **La referencia del objeto está protegida**. Lo siguiente NO está permitido.
|
||||
|
||||
```javascript
|
||||
const obj = { a: 3 };
|
||||
obj = { b: 5 } // not allowed
|
||||
```
|
||||
|
||||
- **El valor del objeto no está protegido**. Lo siguiente SÍ está permitido:
|
||||
|
||||
```javascript
|
||||
const obj = { a: 3 };
|
||||
obj.a = 5; // allowed
|
||||
```
|
||||
|
||||
Arriba estás cambiando el valor del objeto pero no la referencia en sí, lo cual está permitido.
|
||||
|
||||
> Nota, un `const` significa que la referencia está protegida contra reasignación. Sin embargo, el valor no es _inmutable_ y puede cambiar, especialmente si es una construcción compleja como un objeto.
|
||||
|
||||
## Tipos de Datos
|
||||
|
||||
Las variables pueden almacenar muchos tipos diferentes de valores, como números y texto. Estos diversos tipos de valores se conocen como **tipo de dato**. Los tipos de datos son una parte importante del desarrollo de software porque ayudan a los desarrolladores a tomar decisiones sobre cómo debe escribirse el código y cómo debe ejecutarse el software. Además, algunos tipos de datos tienen características únicas que ayudan a transformar o extraer información adicional de un valor.
|
||||
|
||||
✅ Los tipos de datos también se conocen como primitivas de datos de JavaScript, ya que son los tipos de datos de nivel más bajo que proporciona el lenguaje. Hay 7 tipos de datos primitivos: string, number, bigint, boolean, undefined, null y symbol. Tómate un minuto para visualizar lo que cada una de estas primitivas podría representar. ¿Qué es un `zebra`? ¿Qué tal `0`? ¿`true`?
|
||||
|
||||
### Números
|
||||
|
||||
En la sección anterior, el valor de `myVariable` era un tipo de dato numérico.
|
||||
|
||||
`let myVariable = 123;`
|
||||
|
||||
Las variables pueden almacenar todo tipo de números, incluidos decimales o números negativos. Los números también pueden usarse con operadores aritméticos, cubiertos en la [siguiente sección](../../../../2-js-basics/1-data-types).
|
||||
|
||||
### Operadores Aritméticos
|
||||
|
||||
Hay varios tipos de operadores para usar al realizar funciones aritméticas, y algunos se enumeran aquí:
|
||||
|
||||
| Símbolo | Descripción | Ejemplo |
|
||||
| ------ | ------------------------------------------------------------------------ | -------------------------------- |
|
||||
| `+` | **Suma**: Calcula la suma de dos números | `1 + 2 //respuesta esperada es 3` |
|
||||
| `-` | **Resta**: Calcula la diferencia de dos números | `1 - 2 //respuesta esperada es -1` |
|
||||
| `*` | **Multiplicación**: Calcula el producto de dos números | `1 * 2 //respuesta esperada es 2` |
|
||||
| `/` | **División**: Calcula el cociente de dos números | `1 / 2 //respuesta esperada es 0.5` |
|
||||
| `%` | **Resto**: Calcula el resto de la división de dos números | `1 % 2 //respuesta esperada es 1` |
|
||||
|
||||
✅ ¡Pruébalo! Intenta una operación aritmética en la consola de tu navegador. ¿Te sorprenden los resultados?
|
||||
|
||||
### Cadenas de Texto (Strings)
|
||||
|
||||
Las cadenas de texto son conjuntos de caracteres que se encuentran entre comillas simples o dobles.
|
||||
|
||||
- `'Esto es una cadena de texto'`
|
||||
- `"Esto también es una cadena de texto"`
|
||||
- `let myString = 'Esto es un valor de cadena de texto almacenado en una variable';`
|
||||
|
||||
Recuerda usar comillas al escribir una cadena de texto, de lo contrario JavaScript asumirá que es un nombre de variable.
|
||||
|
||||
### Formateo de Cadenas de Texto
|
||||
|
||||
Las cadenas de texto son textuales y requerirán formateo de vez en cuando.
|
||||
|
||||
Para **concatenar** dos o más cadenas de texto, o unirlas, usa el operador `+`.
|
||||
|
||||
```javascript
|
||||
let myString1 = "Hello";
|
||||
let myString2 = "World";
|
||||
|
||||
myString1 + myString2 + "!"; //HelloWorld!
|
||||
myString1 + " " + myString2 + "!"; //Hello World!
|
||||
myString1 + ", " + myString2 + "!"; //Hello, World!
|
||||
|
||||
```
|
||||
|
||||
✅ ¿Por qué `1 + 1 = 2` en JavaScript, pero `'1' + '1' = 11?` Piénsalo. ¿Qué pasa con `'1' + 1`?
|
||||
|
||||
**Literales de plantilla** son otra forma de formatear cadenas de texto, excepto que en lugar de comillas, se usa el acento grave. Cualquier cosa que no sea texto plano debe colocarse dentro de los marcadores `${ }`. Esto incluye cualquier variable que pueda ser una cadena de texto.
|
||||
|
||||
```javascript
|
||||
let myString1 = "Hello";
|
||||
let myString2 = "World";
|
||||
|
||||
`${myString1} ${myString2}!` //Hello World!
|
||||
`${myString1}, ${myString2}!` //Hello, World!
|
||||
```
|
||||
|
||||
Puedes lograr tus objetivos de formateo con cualquiera de los métodos, pero los literales de plantilla respetarán cualquier espacio y salto de línea.
|
||||
|
||||
✅ ¿Cuándo usarías un literal de plantilla en lugar de una cadena de texto simple?
|
||||
|
||||
### Booleanos
|
||||
|
||||
Los booleanos solo pueden tener dos valores: `true` o `false`. Los booleanos pueden ayudar a tomar decisiones sobre qué líneas de código deben ejecutarse cuando se cumplen ciertas condiciones. En muchos casos, los [operadores](../../../../2-js-basics/1-data-types) ayudan a establecer el valor de un booleano y a menudo notarás y escribirás variables que se inicializan o cuyos valores se actualizan con un operador.
|
||||
|
||||
- `let myTrueBool = true`
|
||||
- `let myFalseBool = false`
|
||||
|
||||
✅ Una variable puede considerarse 'verdadera' si se evalúa como un booleano `true`. Curiosamente, en JavaScript, [todos los valores son verdaderos a menos que se definan como falsos](https://developer.mozilla.org/docs/Glossary/Truthy).
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Desafío
|
||||
|
||||
JavaScript es famoso por sus formas sorprendentes de manejar tipos de datos en ocasiones. Investiga un poco sobre estos 'problemas'. Por ejemplo: ¡la sensibilidad a mayúsculas y minúsculas puede ser un problema! Intenta esto en tu consola: `let age = 1; let Age = 2; age == Age` (resuelve `false` -- ¿por qué?). ¿Qué otros problemas puedes encontrar?
|
||||
|
||||
## Cuestionario Posterior a la Clase
|
||||
[Cuestionario posterior a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/8)
|
||||
|
||||
## Repaso y Estudio Personal
|
||||
|
||||
Echa un vistazo a [esta lista de ejercicios de JavaScript](https://css-tricks.com/snippets/javascript/) y prueba uno. ¿Qué aprendiste?
|
||||
|
||||
## Tarea
|
||||
|
||||
[Práctica de Tipos de Datos](assignment.md)
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "3869244ceda606c4969d8cdd82679867",
|
||||
"translation_date": "2025-08-24T12:23:59+00:00",
|
||||
"source_file": "2-js-basics/1-data-types/assignment.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Práctica de Tipos de Datos
|
||||
|
||||
## Instrucciones
|
||||
|
||||
Imagina que estás creando un carrito de compras. Escribe algo de documentación sobre los tipos de datos que necesitarías para completar tu experiencia de compra. ¿Cómo llegaste a tus elecciones?
|
||||
|
||||
## Rúbrica
|
||||
|
||||
Criterios | Ejemplar | Adecuado | Necesita Mejorar
|
||||
--- | --- | --- | --- |
|
||||
||Se enumeran y exploran en detalle los seis tipos de datos, documentando su uso|Se exploran cuatro tipos de datos|Se exploran dos tipos de datos|
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,208 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "b4612bbb9ace984f374fcc80e3e035ad",
|
||||
"translation_date": "2025-08-24T12:15:52+00:00",
|
||||
"source_file": "2-js-basics/2-functions-methods/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Conceptos básicos de JavaScript: Métodos y Funciones
|
||||
|
||||

|
||||
> Sketchnote por [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Cuestionario previo a la clase
|
||||
[Cuestionario previo a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/9)
|
||||
|
||||
Cuando pensamos en escribir código, siempre queremos asegurarnos de que sea legible. Aunque suene contradictorio, el código se lee muchas más veces de lo que se escribe. Una herramienta clave en el arsenal de un desarrollador para garantizar un código mantenible es la **función**.
|
||||
|
||||
[](https://youtube.com/watch?v=XgKsD6Zwvlc "Métodos y Funciones")
|
||||
|
||||
> 🎥 Haz clic en la imagen de arriba para ver un video sobre métodos y funciones.
|
||||
|
||||
> Puedes tomar esta lección en [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-functions/?WT.mc_id=academic-77807-sagibbon)!
|
||||
|
||||
## Funciones
|
||||
|
||||
En esencia, una función es un bloque de código que podemos ejecutar bajo demanda. Esto es perfecto para escenarios en los que necesitamos realizar la misma tarea varias veces; en lugar de duplicar la lógica en múltiples ubicaciones (lo que dificultaría su actualización en el futuro), podemos centralizarla en un solo lugar y llamarla cuando necesitemos realizar la operación; incluso puedes llamar funciones desde otras funciones.
|
||||
|
||||
Igual de importante es la capacidad de nombrar una función. Aunque pueda parecer trivial, el nombre proporciona una forma rápida de documentar una sección de código. Puedes pensar en esto como una etiqueta en un botón. Si hago clic en un botón que dice "Cancelar temporizador", sé que detendrá el reloj.
|
||||
|
||||
## Crear y llamar a una función
|
||||
|
||||
La sintaxis de una función se ve de la siguiente manera:
|
||||
|
||||
```javascript
|
||||
function nameOfFunction() { // function definition
|
||||
// function definition/body
|
||||
}
|
||||
```
|
||||
|
||||
Si quisiera crear una función para mostrar un saludo, podría verse así:
|
||||
|
||||
```javascript
|
||||
function displayGreeting() {
|
||||
console.log('Hello, world!');
|
||||
}
|
||||
```
|
||||
|
||||
Siempre que queramos llamar (o invocar) nuestra función, usamos el nombre de la función seguido de `()`. Vale la pena señalar que nuestra función puede definirse antes o después de decidir llamarla; el compilador de JavaScript la encontrará por ti.
|
||||
|
||||
```javascript
|
||||
// calling our function
|
||||
displayGreeting();
|
||||
```
|
||||
|
||||
> **NOTE:** Existe un tipo especial de función conocida como **método**, ¡que ya has estado usando! De hecho, lo vimos en nuestra demostración anterior cuando usamos `console.log`. Lo que diferencia un método de una función es que un método está adjunto a un objeto (`console` en nuestro ejemplo), mientras que una función es independiente. Escucharás a muchos desarrolladores usar estos términos indistintamente.
|
||||
|
||||
### Mejores prácticas para funciones
|
||||
|
||||
Hay algunas mejores prácticas que debes tener en cuenta al crear funciones:
|
||||
|
||||
- Como siempre, usa nombres descriptivos para saber qué hará la función.
|
||||
- Usa **camelCasing** para combinar palabras.
|
||||
- Mantén tus funciones enfocadas en una tarea específica.
|
||||
|
||||
## Pasar información a una función
|
||||
|
||||
Para hacer que una función sea más reutilizable, a menudo querrás pasarle información. Si consideramos nuestro ejemplo de `displayGreeting` anterior, solo mostrará **Hello, world!**. No es la función más útil que uno podría crear. Si queremos hacerla un poco más flexible, como permitir que alguien especifique el nombre de la persona a saludar, podemos agregar un **parámetro**. Un parámetro (a veces también llamado **argumento**) es información adicional enviada a una función.
|
||||
|
||||
Los parámetros se enumeran en la parte de definición dentro de paréntesis y están separados por comas, como se muestra a continuación:
|
||||
|
||||
```javascript
|
||||
function name(param, param2, param3) {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Podemos actualizar nuestro `displayGreeting` para aceptar un nombre y mostrarlo.
|
||||
|
||||
```javascript
|
||||
function displayGreeting(name) {
|
||||
const message = `Hello, ${name}!`;
|
||||
console.log(message);
|
||||
}
|
||||
```
|
||||
|
||||
Cuando queramos llamar a nuestra función y pasarle el parámetro, lo especificamos en los paréntesis.
|
||||
|
||||
```javascript
|
||||
displayGreeting('Christopher');
|
||||
// displays "Hello, Christopher!" when run
|
||||
```
|
||||
|
||||
## Valores predeterminados
|
||||
|
||||
Podemos hacer que nuestra función sea aún más flexible agregando más parámetros. Pero, ¿qué pasa si no queremos que se especifique cada valor? Siguiendo con nuestro ejemplo de saludo, podríamos dejar el nombre como obligatorio (necesitamos saber a quién estamos saludando), pero queremos permitir que el saludo en sí se personalice según se desee. Si alguien no quiere personalizarlo, proporcionamos un valor predeterminado en su lugar. Para proporcionar un valor predeterminado a un parámetro, lo configuramos de la misma manera que configuramos un valor para una variable: `parameterName = 'defaultValue'`. Para ver un ejemplo completo:
|
||||
|
||||
```javascript
|
||||
function displayGreeting(name, salutation='Hello') {
|
||||
console.log(`${salutation}, ${name}`);
|
||||
}
|
||||
```
|
||||
|
||||
Cuando llamamos a la función, podemos decidir si queremos establecer un valor para `salutation`.
|
||||
|
||||
```javascript
|
||||
displayGreeting('Christopher');
|
||||
// displays "Hello, Christopher"
|
||||
|
||||
displayGreeting('Christopher', 'Hi');
|
||||
// displays "Hi, Christopher"
|
||||
```
|
||||
|
||||
## Valores de retorno
|
||||
|
||||
Hasta ahora, la función que hemos creado siempre se mostrará en la [consola](https://developer.mozilla.org/docs/Web/API/console). A veces esto puede ser exactamente lo que buscamos, especialmente cuando creamos funciones que llamarán a otros servicios. Pero, ¿qué pasa si quiero crear una función auxiliar para realizar un cálculo y proporcionar el valor de vuelta para que pueda usarlo en otro lugar?
|
||||
|
||||
Podemos hacer esto utilizando un **valor de retorno**. Un valor de retorno es devuelto por la función y puede almacenarse en una variable de la misma manera que podríamos almacenar un valor literal como una cadena o un número.
|
||||
|
||||
Si una función devuelve algo, entonces se utiliza la palabra clave `return`. La palabra clave `return` espera un valor o referencia de lo que se está devolviendo, como se muestra a continuación:
|
||||
|
||||
```javascript
|
||||
return myVariable;
|
||||
```
|
||||
|
||||
Podríamos crear una función para crear un mensaje de saludo y devolver el valor al que lo llama.
|
||||
|
||||
```javascript
|
||||
function createGreetingMessage(name) {
|
||||
const message = `Hello, ${name}`;
|
||||
return message;
|
||||
}
|
||||
```
|
||||
|
||||
Cuando llamemos a esta función, almacenaremos el valor en una variable. Esto es muy similar a cómo estableceríamos una variable con un valor estático (como `const name = 'Christopher'`).
|
||||
|
||||
```javascript
|
||||
const greetingMessage = createGreetingMessage('Christopher');
|
||||
```
|
||||
|
||||
## Funciones como parámetros para funciones
|
||||
|
||||
A medida que avances en tu carrera de programación, te encontrarás con funciones que aceptan funciones como parámetros. Este truco ingenioso se usa comúnmente cuando no sabemos cuándo ocurrirá o se completará algo, pero sabemos que necesitamos realizar una operación en respuesta.
|
||||
|
||||
Como ejemplo, considera [setTimeout](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout), que inicia un temporizador y ejecutará código cuando se complete. Necesitamos decirle qué código queremos ejecutar. ¡Suena como un trabajo perfecto para una función!
|
||||
|
||||
Si ejecutas el código a continuación, después de 3 segundos verás el mensaje **Han pasado 3 segundos**.
|
||||
|
||||
```javascript
|
||||
function displayDone() {
|
||||
console.log('3 seconds has elapsed');
|
||||
}
|
||||
// timer value is in milliseconds
|
||||
setTimeout(displayDone, 3000);
|
||||
```
|
||||
|
||||
### Funciones anónimas
|
||||
|
||||
Echemos otro vistazo a lo que hemos construido. Estamos creando una función con un nombre que se usará una sola vez. A medida que nuestra aplicación se vuelve más compleja, podemos vernos creando muchas funciones que solo se llamarán una vez. Esto no es ideal. Como resulta, ¡no siempre necesitamos proporcionar un nombre!
|
||||
|
||||
Cuando pasamos una función como parámetro, podemos omitir crear una de antemano y, en su lugar, construirla como parte del parámetro. Usamos la misma palabra clave `function`, pero en su lugar la construimos como un parámetro.
|
||||
|
||||
Reescribamos el código anterior para usar una función anónima:
|
||||
|
||||
```javascript
|
||||
setTimeout(function() {
|
||||
console.log('3 seconds has elapsed');
|
||||
}, 3000);
|
||||
```
|
||||
|
||||
Si ejecutas nuestro nuevo código, notarás que obtenemos los mismos resultados. Hemos creado una función, ¡pero no tuvimos que darle un nombre!
|
||||
|
||||
### Funciones de flecha
|
||||
|
||||
Un atajo común en muchos lenguajes de programación (incluido JavaScript) es la capacidad de usar lo que se llama una **función de flecha** o **función de flecha gorda**. Utiliza un indicador especial `=>`, que parece una flecha, ¡de ahí el nombre! Al usar `=>`, podemos omitir la palabra clave `function`.
|
||||
|
||||
Reescribamos nuestro código una vez más para usar una función de flecha:
|
||||
|
||||
```javascript
|
||||
setTimeout(() => {
|
||||
console.log('3 seconds has elapsed');
|
||||
}, 3000);
|
||||
```
|
||||
|
||||
### Cuándo usar cada estrategia
|
||||
|
||||
Ahora has visto que tenemos tres formas de pasar una función como parámetro y podrías preguntarte cuándo usar cada una. Si sabes que usarás la función más de una vez, créala de forma normal. Si la usarás solo en una ubicación, generalmente es mejor usar una función anónima. Si usarás una función de flecha o la sintaxis más tradicional de `function` depende de ti, pero notarás que la mayoría de los desarrolladores modernos prefieren `=>`.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Desafío
|
||||
|
||||
¿Puedes articular en una oración la diferencia entre funciones y métodos? ¡Inténtalo!
|
||||
|
||||
## Cuestionario posterior a la clase
|
||||
[Cuestionario posterior a la clase](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/10)
|
||||
|
||||
## Repaso y autoestudio
|
||||
|
||||
Vale la pena [leer un poco más sobre las funciones de flecha](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), ya que se usan cada vez más en bases de código. Practica escribiendo una función y luego reescribiéndola con esta sintaxis.
|
||||
|
||||
## Tarea
|
||||
|
||||
[Diviértete con las funciones](assignment.md)
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,25 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "8973f96157680a13e9446e4bb540ee57",
|
||||
"translation_date": "2025-08-24T12:18:12+00:00",
|
||||
"source_file": "2-js-basics/2-functions-methods/assignment.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Diversión con Funciones
|
||||
|
||||
## Instrucciones
|
||||
|
||||
Crea diferentes funciones, tanto funciones que devuelvan algo como funciones que no devuelvan nada.
|
||||
|
||||
Intenta crear una función que tenga una mezcla de parámetros y parámetros con valores predeterminados.
|
||||
|
||||
## Rúbrica
|
||||
|
||||
| Criterios | Ejemplar | Adecuado | Necesita Mejora |
|
||||
| --------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------- |
|
||||
| | Se ofrece una solución con dos o más funciones bien diseñadas y con parámetros diversos | Se ofrece una solución funcional con una función y pocos parámetros | La solución tiene errores |
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,52 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "bf62b82567e6f9bdf4abda9ae0ccb64a",
|
||||
"translation_date": "2025-08-24T12:14:49+00:00",
|
||||
"source_file": "2-js-basics/3-making-decisions/assignment.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Operadores
|
||||
|
||||
## Instrucciones
|
||||
|
||||
Experimenta con operadores. Aquí tienes una sugerencia para un programa que puedes implementar:
|
||||
|
||||
Tienes un conjunto de estudiantes de dos sistemas de calificación diferentes.
|
||||
|
||||
### Primer sistema de calificación
|
||||
|
||||
Un sistema de calificación está definido con notas del 1 al 5, donde 3 y superiores significan que apruebas el curso.
|
||||
|
||||
### Segundo sistema de calificación
|
||||
|
||||
El otro sistema de calificación tiene las siguientes notas: `A, A-, B, B-, C, C-`, donde `A` es la mejor nota y `C` es la nota más baja para aprobar.
|
||||
|
||||
### La tarea
|
||||
|
||||
Dado el siguiente arreglo `allStudents` que representa a todos los estudiantes y sus calificaciones, construye un nuevo arreglo `studentsWhoPass` que contenga a todos los estudiantes que aprueban.
|
||||
|
||||
> TIP, utiliza un bucle for, if...else y operadores de comparación:
|
||||
|
||||
```javascript
|
||||
let allStudents = [
|
||||
'A',
|
||||
'B-',
|
||||
1,
|
||||
4,
|
||||
5,
|
||||
2
|
||||
]
|
||||
|
||||
let studentsWhoPass = [];
|
||||
```
|
||||
|
||||
## Rúbrica
|
||||
|
||||
| Criterios | Ejemplar | Adecuado | Necesita Mejoras |
|
||||
| --------- | ----------------------------- | ----------------------------- | ------------------------------- |
|
||||
| | Se presenta una solución completa | Se presenta una solución parcial | Se presenta una solución con errores |
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Aunque nos esforzamos por garantizar la precisión, tenga en cuenta que las traducciones automatizadas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
@ -0,0 +1,145 @@
|
||||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "3f7f87871312cf6cc12662da7d973182",
|
||||
"translation_date": "2025-08-24T12:18:55+00:00",
|
||||
"source_file": "2-js-basics/4-arrays-loops/README.md",
|
||||
"language_code": "es"
|
||||
}
|
||||
-->
|
||||
# Conceptos básicos de JavaScript: Arrays y Bucles
|
||||
|
||||

|
||||
> Sketchnote por [Tomomi Imura](https://twitter.com/girlie_mac)
|
||||
|
||||
## Cuestionario previo a la lección
|
||||
[Cuestionario previo a la lección](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/13)
|
||||
|
||||
Esta lección cubre los conceptos básicos de JavaScript, el lenguaje que proporciona interactividad en la web. En esta lección, aprenderás sobre arrays y bucles, que se utilizan para manipular datos.
|
||||
|
||||
[](https://youtube.com/watch?v=1U4qTyq02Xw "Arrays")
|
||||
|
||||
[](https://www.youtube.com/watch?v=Eeh7pxtTZ3k "Bucles")
|
||||
|
||||
> 🎥 Haz clic en las imágenes de arriba para ver videos sobre arrays y bucles.
|
||||
|
||||
> Puedes tomar esta lección en [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-arrays/?WT.mc_id=academic-77807-sagibbon)!
|
||||
|
||||
## Arrays
|
||||
|
||||
Trabajar con datos es una tarea común en cualquier lenguaje, y es mucho más fácil cuando los datos están organizados en un formato estructurado, como los arrays. Con los arrays, los datos se almacenan en una estructura similar a una lista. Una gran ventaja de los arrays es que puedes almacenar diferentes tipos de datos en un solo array.
|
||||
|
||||
✅ ¡Los arrays están por todas partes! ¿Puedes pensar en un ejemplo de la vida real de un array, como un conjunto de paneles solares?
|
||||
|
||||
La sintaxis de un array es un par de corchetes.
|
||||
|
||||
```javascript
|
||||
let myArray = [];
|
||||
```
|
||||
|
||||
Este es un array vacío, pero los arrays pueden declararse ya poblados con datos. Los valores múltiples en un array se separan con una coma.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
```
|
||||
|
||||
A los valores del array se les asigna un valor único llamado **índice**, un número entero que se asigna según su distancia desde el inicio del array. En el ejemplo anterior, el valor de cadena "Chocolate" tiene un índice de 0, y el índice de "Rocky Road" es 4. Usa el índice con corchetes para recuperar, cambiar o insertar valores en el array.
|
||||
|
||||
✅ ¿Te sorprende que los arrays comiencen en el índice cero? En algunos lenguajes de programación, los índices comienzan en 1. Hay una historia interesante detrás de esto, que puedes [leer en Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
iceCreamFlavors[2]; //"Vanilla"
|
||||
```
|
||||
|
||||
Puedes usar el índice para cambiar un valor, así:
|
||||
|
||||
```javascript
|
||||
iceCreamFlavors[4] = "Butter Pecan"; //Changed "Rocky Road" to "Butter Pecan"
|
||||
```
|
||||
|
||||
Y puedes insertar un nuevo valor en un índice dado de esta manera:
|
||||
|
||||
```javascript
|
||||
iceCreamFlavors[5] = "Cookie Dough"; //Added "Cookie Dough"
|
||||
```
|
||||
|
||||
✅ Una forma más común de agregar valores a un array es utilizando operadores como array.push()
|
||||
|
||||
Para saber cuántos elementos hay en un array, usa la propiedad `length`.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
iceCreamFlavors.length; //5
|
||||
```
|
||||
|
||||
✅ ¡Pruébalo tú mismo! Usa la consola de tu navegador para crear y manipular un array de tu propia creación.
|
||||
|
||||
## Bucles
|
||||
|
||||
Los bucles nos permiten realizar tareas repetitivas o **iterativas**, y pueden ahorrar mucho tiempo y código. Cada iteración puede variar en sus variables, valores y condiciones. Hay diferentes tipos de bucles en JavaScript, y todos tienen pequeñas diferencias, pero esencialmente hacen lo mismo: recorrer datos.
|
||||
|
||||
### Bucle For
|
||||
|
||||
El bucle `for` requiere 3 partes para iterar:
|
||||
- `contador` Una variable que generalmente se inicializa con un número que cuenta el número de iteraciones
|
||||
- `condición` Expresión que utiliza operadores de comparación para detener el bucle cuando sea `false`
|
||||
- `expresión de iteración` Se ejecuta al final de cada iteración, generalmente se usa para cambiar el valor del contador
|
||||
|
||||
```javascript
|
||||
// Counting up to 10
|
||||
for (let i = 0; i < 10; i++) {
|
||||
console.log(i);
|
||||
}
|
||||
```
|
||||
|
||||
✅ Ejecuta este código en la consola de un navegador. ¿Qué sucede cuando haces pequeños cambios al contador, la condición o la expresión de iteración? ¿Puedes hacer que funcione al revés, creando una cuenta regresiva?
|
||||
|
||||
### Bucle While
|
||||
|
||||
A diferencia de la sintaxis del bucle `for`, los bucles `while` solo requieren una condición que detendrá el bucle cuando la condición se vuelva `false`. Las condiciones en los bucles generalmente dependen de otros valores como contadores, y deben gestionarse durante el bucle. Los valores iniciales para los contadores deben crearse fuera del bucle, y cualquier expresión para cumplir una condición, incluido el cambio del contador, debe mantenerse dentro del bucle.
|
||||
|
||||
```javascript
|
||||
//Counting up to 10
|
||||
let i = 0;
|
||||
while (i < 10) {
|
||||
console.log(i);
|
||||
i++;
|
||||
}
|
||||
```
|
||||
|
||||
✅ ¿Por qué elegirías un bucle for en lugar de un bucle while? 17,000 personas tuvieron la misma pregunta en StackOverflow, y algunas de las opiniones [podrían interesarte](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
|
||||
|
||||
## Bucles y Arrays
|
||||
|
||||
Los arrays se usan a menudo con bucles porque la mayoría de las condiciones requieren la longitud del array para detener el bucle, y el índice también puede ser el valor del contador.
|
||||
|
||||
```javascript
|
||||
let iceCreamFlavors = ["Chocolate", "Strawberry", "Vanilla", "Pistachio", "Rocky Road"];
|
||||
|
||||
for (let i = 0; i < iceCreamFlavors.length; i++) {
|
||||
console.log(iceCreamFlavors[i]);
|
||||
} //Ends when all flavors are printed
|
||||
```
|
||||
|
||||
✅ Experimenta recorriendo un array de tu propia creación en la consola de tu navegador.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Desafío
|
||||
|
||||
Existen otras formas de recorrer arrays además de los bucles for y while. Hay [forEach](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), [for-of](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for...of) y [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map). Reescribe tu bucle de array utilizando una de estas técnicas.
|
||||
|
||||
## Cuestionario posterior a la lección
|
||||
[Cuestionario posterior a la lección](https://ashy-river-0debb7803.1.azurestaticapps.net/quiz/14)
|
||||
|
||||
## Repaso y autoestudio
|
||||
|
||||
Los arrays en JavaScript tienen muchos métodos asociados que son extremadamente útiles para la manipulación de datos. [Lee sobre estos métodos](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) y prueba algunos de ellos (como push, pop, slice y splice) en un array de tu creación.
|
||||
|
||||
## Tarea
|
||||
|
||||
[Recorrer un Array](assignment.md)
|
||||
|
||||
**Descargo de responsabilidad**:
|
||||
Este documento ha sido traducido utilizando el servicio de traducción automática [Co-op Translator](https://github.com/Azure/co-op-translator). Si bien nos esforzamos por lograr precisión, tenga en cuenta que las traducciones automáticas pueden contener errores o imprecisiones. El documento original en su idioma nativo debe considerarse como la fuente autorizada. Para información crítica, se recomienda una traducción profesional realizada por humanos. No nos hacemos responsables de malentendidos o interpretaciones erróneas que puedan surgir del uso de esta traducción.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue