| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung |
| de:modul:m291:learningunits:lu11:theorie:a_fetching_data [2026/05/10 23:46] – gkoch | de:modul:m291:learningunits:lu11:theorie:a_fetching_data [2026/05/11 00:04] (aktuell) – gkoch |
|---|
| </WRAP> | </WRAP> |
| |
| ---- | |
| |
| ===== Das Problem: Netzwerkanfragen brauchen Zeit ===== | ===== Das Problem: Netzwerkanfragen brauchen Zeit ===== |
| Die Lösung: **asynchrones JavaScript** – der Browser wartet auf die Daten, aber der Rest der App läuft währenddessen weiter. | Die Lösung: **asynchrones JavaScript** – der Browser wartet auf die Daten, aber der Rest der App läuft währenddessen weiter. |
| |
| ---- | {{:de:modul:m291:learningunits:lu11:theorie:async.png?direct&900| Async JavaScript}} |
| |
| ===== async / await ===== | ===== async / await ===== |
| </code> | </code> |
| </WRAP> | </WRAP> |
| | <WRAP box center round 80%> |
| ^ Schlüsselwort ^ Bedeutung ^ | ^ Schlüsselwort ^ Bedeutung ^ |
| | ''async'' | Diese Funktion ist asynchron. Sie erlaubt die Verwendung von ''await'' und blockiert nicht den Rest der App. | | | ''async'' | Diese Funktion ist asynchron. Sie erlaubt die Verwendung von ''await'' und blockiert nicht den Rest der App. | |
| | ''fetch()'' | Sendet einen HTTP GET-Request an die angegebene URL und gibt ein Promise zurück. | | | ''fetch()'' | Sendet einen HTTP GET-Request an die angegebene URL und gibt ein Promise zurück. | |
| | ''response.json()'' | Liest den Body der Antwort und wandelt ihn von JSON in ein JavaScript-Objekt um. Auch das ist asynchron – daher auch hier ''await''. | | | ''response.json()'' | Liest den Body der Antwort und wandelt ihn von JSON in ein JavaScript-Objekt um. Auch das ist asynchron – daher auch hier ''await''. | |
| | </WRAP> |
| <WRAP tip round> | <WRAP tip round> |
| **Warum zwei ''await''?** ''fetch()'' liefert zuerst nur die Antwort-Hülle (Statuscode, Header). Der eigentliche Inhalt (Body) kommt als Stream und muss erst mit ''response.json()'' ausgelesen werden. Beides dauert einen Moment – daher je ein ''await''. | **Warum zwei ''await''?** ''fetch()'' liefert zuerst nur die Antwort-Hülle (Statuscode, Header). Der eigentliche Inhalt (Body) kommt als Stream und muss erst mit ''response.json()'' ausgelesen werden. Beides dauert einen Moment – daher je ein ''await''. |
| </WRAP> | </WRAP> |
| |
| ---- | |
| |
| ===== try / catch / finally ===== | ===== try / catch / finally ===== |
| |
| Was passiert, wenn die API nicht erreichbar ist oder einen Fehler zurückgibt? Ohne Fehlerbehandlung bricht die App still zusammen. Mit ''try / catch'' fangen wir Fehler ab und zeigen eine verständliche Meldung an. | Was passiert, wenn die API nicht erreichbar ist oder einen Fehler zurückgibt? Ohne Fehlerbehandlung crashed die Applikation. Mit ''try / catch'' fangen wir Fehler ab und zeigen eine verständliche Meldung an. |
| |
| <WRAP box center round 80%> | <WRAP box center round 80%> |
| </WRAP> | </WRAP> |
| |
| | <WRAP box center round 80%> |
| ^ Block ^ Wann? ^ | ^ Block ^ Wann? ^ |
| | ''try'' | Enthält den Code, der fehlschlagen könnte | | | ''try'' | Enthält den Code, der fehlschlagen könnte | |
| | ''catch'' | Wird ausgeführt, wenn im ''try''-Block ein Fehler auftritt | | | ''catch'' | Wird ausgeführt, wenn im ''try''-Block ein Fehler auftritt | |
| | ''finally'' | Wird immer ausgeführt – ideal um z.B. ''isLoading'' zurückzusetzen | | | ''finally'' | Wird immer ausgeführt – ideal um z.B. ''isLoading'' zurückzusetzen | |
| | </WRAP> |
| ---- | |
| |
| ===== onMounted ===== | ===== onMounted ===== |
| ''onMounted'' registriert eine Funktion, die Vue automatisch aufruft, sobald die Komponente das erste Mal im DOM gerendert wurde. Das ist der richtige Zeitpunkt, um Daten zu laden – das HTML ist bereit, die Daten können sofort angezeigt werden. | ''onMounted'' registriert eine Funktion, die Vue automatisch aufruft, sobald die Komponente das erste Mal im DOM gerendert wurde. Das ist der richtige Zeitpunkt, um Daten zu laden – das HTML ist bereit, die Daten können sofort angezeigt werden. |
| |
| ---- | |
| |
| ===== v-if / v-else-if / v-else ===== | ===== v-if / v-else-if / v-else ===== |
| </WRAP> | </WRAP> |
| |
| | <WRAP round box 80% center> |
| ^ Direktive ^ Wann wird dieses Element angezeigt? ^ | ^ Direktive ^ Wann wird dieses Element angezeigt? ^ |
| | ''v-if="isLoading"'' | Solange die Daten noch geladen werden | | | ''v-if="isLoading"'' | Solange die Daten noch geladen werden | |
| |
| Diese drei Blöcke schliessen sich gegenseitig aus – Vue zeigt immer nur einen davon an. | Diese drei Blöcke schliessen sich gegenseitig aus – Vue zeigt immer nur einen davon an. |
| | </WRAP> |
| ---- | |
| |
| ===== Der vollständige Ablauf ===== | ===== Der vollständige Ablauf ===== |
| ↓ | ↓ |
| 7. isLoading = false → Ladeanzeige verschwindet | 7. isLoading = false → Ladeanzeige verschwindet |
| </code> | |
| </WRAP> | |
| |
| ---- | |
| |
| ===== Hinweis: Änderung der Props ===== | |
| |
| <WRAP important round> | |
| Im neuen Code werden ''question'' und ''answer'' als **separate Props** übergeben – nicht mehr als ein ''faq''-Objekt: | |
| |
| <code html> | |
| <!-- Neu --> | |
| <AccordionItem :question="item.question" :answer="item.answer" /> | |
| </code> | |
| |
| Das bedeutet: ''AccordionItem.vue'' muss angepasst werden. Ersetzen Sie ''defineProps({ faq: Object })'' durch: | |
| |
| <code javascript> | |
| defineProps({ | |
| question: String, | |
| answer: String | |
| }) | |
| </code> | |
| |
| Und im Template von ''AccordionItem.vue'': | |
| <code html> | |
| <button>{{ question }}</button> | |
| <div class="panel">{{ answer }}</div> | |
| </code> | </code> |
| </WRAP> | </WRAP> |