Lebenszyklus und Datenabfragen
In diesem Kapitel lernst du die Lifecycle-Hooks von Vue3 kennen und verwendest fetch, um Blog-Daten zum richtigen Zeitpunkt aus einer JSON-Datei zu laden.
Was ist ein Lebenszyklus?
Jede Vue-Komponente durchläuft eine Reihe von Phasen von der Erstellung bis zur Zerstörung; diese Phasen werden als "Lebenszyklus" bezeichnet.
Vue stellt in jeder Phase entsprechendeHook-Funktionenbereit, mit denen du Code zu bestimmten Zeitpunkten ausführen kannst.
Wenn du zum Beispiel Daten anfordern möchtest, nachdem die Komponente fertig geladen ist, musst duonMounteddiesen Hook verwenden.
Überblick über Vue3 Lifecycle-Hooks
| Hook-Funktion | Ausführungszeitpunkt | Häufige Anwendungsfälle |
|---|---|---|
| setup() | Komponenteninitialisierung, wird am frühesten ausgeführt | Reaktive Daten und berechnete Eigenschaften definieren |
| onBeforeMount | Bevor die Komponente in das DOM eingebunden wird | Weniger häufig verwendet |
| onMounted | Nachdem die Komponente in das DOM eingebunden wurde | Netzwerkanfragen stellen, Bibliotheken von Drittanbietern initialisieren, DOM-Referenzen abrufen |
| onBeforeUpdate | Bevor sich Daten ändern und das DOM aktualisiert wird | Weniger häufig verwendet |
| onUpdated | Nach Datenänderungen und DOM-Aktualisierungen | Operationen nach DOM-Aktualisierungen |
| onBeforeUnmount | Bevor die Komponente zerstört wird | Timer löschen, Abonnements kündigen, Event-Listener entfernen |
| onUnmounted | Nachdem die Komponente zerstört wurde | Aufräumarbeiten bestätigen |
Im Blog-Projekt verwenden wir am häufigstenonMounted— um Artikeldaten nach dem Laden der Seite abzurufen.
Lifecycle-Hooks müssen geschrieben werden in
<script setup>setup und können nicht innerhalb von async-Funktionen oder bedingten Anweisungen platziert werden. Vue bestimmt anhand der Reihenfolge der Aufrufe, zu welcher Komponente sie gehören.
Grundlegende Verwendung von onMounted
Beispiel
import { ref, onMounted } from 'vue'
const message = ref('Wird geladen...')
// onMounted wird ausgeführt, nachdem die Komponente auf der Seite gemountet wurde
onMounted(() => {
// Zu diesem Zeitpunkt ist das Rendern des DOM abgeschlossen, daher ist es sicher, das DOM zu manipulieren oder Anfragen zu senden.
console.log('Die Komponente wurde eingebunden, kann jetzt mit dem Laden von Daten beginnen')
message.value = 'Laden der Daten abgeschlossen!'
})
</script>
<template>
<p>{{ message }}</p>
</template>
Eine Komponente kann onMounted mehrmals aufrufen, und sie werden in der Reihenfolge ihrer Registrierung ausgeführt.
JSON-Daten mit fetch laden
Wir werden die Artikeldaten in einer JSON-Datei ablegen und dann fetch in onMounted verwenden, um sie zu laden.
Schritt 1: Eine Datendatei erstellen
Beispiel
[
{
"id": 1,
"title": "Vue3 Kompletter Anfängerleitfaden",
"summary": "Von Null an Vue3 Composition API lernen, einschließlich ref, reactive, computed und weiterer Kernkonzepte.",
"content": "<h2>Warum Vue3 lernen?</h2><p>Vue3 ist eines der derzeit beliebtesten Frontend-Frameworks...</p>",
"category": "Vue",
"date": "2024-05-10"
},
{
"id": 2,
"title": "Asynchrone Programmierung in JavaScript erklärt"
"summary": "Ein Artikel zum Verständnis von Promise, async/await, Event-Loop und Microtask-Queue.",
"content": "<h2>Was ist asynchron?</h2><p>JS ist single-threaded...</p>",
"category": "JavaScript",
"date": "2024-05-08"
},
{
"id": 3,
"title": "CSS Grid Layout in Aktion"
"summary": "Komplexe responsive Layouts lassen sich mit CSS Grid einfach umsetzen.",
"content": "<h2>Erste Schritte mit Grid</h2><p>Grid ist ein zweidimensionales Layout-System...</p>",
"category": "CSS",
"date": "2024-05-05"
}
]
Die JSON-Datei wird im
public/Verzeichnis. Vite stellt sie direkt als statische Datei bereit. Im Browser können Sie darauf zugreifen über/posts.jsondirekt. Dateien, die in public abgelegt werden, werden nicht kompiliert; sie werden unverändert in die Build-Ausgabe kopiert.
Schritt 2: Daten in der Komponente abrufen
Beispiel
<script setup>
import { ref, onMounted } from 'vue'
import BlogCard from '../components/BlogCard.vue'
import CategoryFilter from '../components/CategoryFilter.vue'
const articles = ref([]) // anfängliches leeres Array
const isLoading = ref(true) // Ladezustand
const error = ref(null) // Fehlermeldung
// Artikeldaten asynchron laden
async function fetchPosts() {
isLoading.value = true
error.value = null
try {
const response = await fetch('/posts.json')
// Prüfen, ob die Antwort erfolgreich ist (löst bei 404 oder 500 einen Fehler aus)
if (!response.ok) {
throw new Error(`Laden fehlgeschlagen: HTTP ${response.status}`)
}
const data = await response.json()
articles.value = data
} catch (err) {
error.value = err.message
console.error('Fehler beim Laden der Artikeldaten:', err)
} finally {
isLoading.value = false
}
}
// Daten sofort nach dem Mounten der Komponente laden
onMounted(() => {
fetchPosts()
})
</script>
<template>
<div class="home">
<h2>Neueste Artikel</h2>
<!-- Ladezustand -->
<p v-if="isLoading" class="status-msg">Wird geladen, bitte warten...</p>
<!-- Fehlerzustand -->
<p v-else-if="error" class="status-msg error">
Laden fehlgeschlagen: {{ error }}
<button @click="fetchPosts">Erneut versuchen</button>
</p>
<!-- Leerer Datenzustand -->
<p v-else-if="articles.length === 0" class="status-msg">
Noch keine Artikel, bitte schauen Sie bald wieder vorbei.
</p>
<!-- Normale Datenanzeige -->
<template v-else>
<div class="article-grid">
<BlogCard
v-for="article in articles"
:key="article.id"
:id="article.id"
:title="article.title"
:summary="article.summary"
:date="article.date"
:category="article.category"
/>
</div>
</template>
</div>
</template>
<style scoped>
.status-msg {
text-align: center;
padding: 60px 0;
font-size: 16px;
color: #999;
}
.error { color: #e74c3c; }
.error button {
margin-left: 10px;
padding: 4px 12px;
cursor: pointer;
}
</style>
Umgang mit drei Zuständen asynchroner Anfragen
Jede Datenanfrage sollte die folgenden drei UI-Zustände abdecken, andernfalls ist die Benutzererfahrung schlecht:
| State | Wann es erscheint | UI-Darstellung |
|---|---|---|
| Wird geladen | Nachdem die Anfrage gesendet wurde, bevor die Antwort zurückkehrt | Ladeanimation, Skeleton-Screen |
| Erfolg | Daten werden korrekt zurückgegeben | Inhalt normal rendern |
| Fehler | Netzwerkfehler, Serverausnahme | Fehlermeldung + Wiederholen-Button |
Du kannst auch einen vierten Zustand behandeln—leere Daten(die Anfrage ist erfolgreich, gibt aber ein leeres Array zurück), wodurch Nutzer eine klare Nachricht statt einer leeren Seite erhalten.
Praktisch: Stelle die Detailseite ebenfalls auf Fetch-Laden um
Die Detailseite muss den entsprechenden Artikel anhand der ID in der URL aus dem JSON finden.
Du kannst die Logik zum Laden der Daten wiederverwenden—rufe auch fetch auf der Detailseite auf und filtere dann.
Beispiel
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute, RouterLink } from 'vue-router'
const route = useRoute()
const id = Number(route.params.id)
const posts = ref([]) // alle Beiträge
const isLoading = ref(true)
const error = ref(null)
// Aktuellen Artikel anhand der ID finden
const article = computed(() => {
return posts.value.find(p => p.id === id)
})
// Alle Artikeldaten laden
async function fetchPosts() {
isLoading.value = true
try {
const res = await fetch('/posts.json')
if (!res.ok) throw new Error('Failed to load')
posts.value = await res.json()
} catch (err) {
error.value = err.message
} finally {
isLoading.value = false
}
}
onMounted(() => {
fetchPosts()
})
</script>
<template>
<div class="post-view">
<p v-if="isLoading">Wird geladen...</p>
<p v-else-if="error">Laden fehlgeschlagen: {{ error }}</p>
<div v-else-if="!article">
<h2>Artikel existiert nicht</h2>
<RouterLink to="/">Zurück zur Startseite</RouterLink>
</div>
<article v-else>
<span class="category-tag">{{ article.category }}</span>
<h1>{{ article.title }}</h1>
<time>{{ article.date }}</time>
<div class="content" v-html="article.content"></div>
<RouterLink to="/">← Zurück zur Startseite</RouterLink>
</article>
</div>
</template>
Kapitelzusammenfassung
In diesem Kapitel hast du den wesentlichsten Vue3-Lifecycle-Hook onMounted gemeistert, fetch verwendet, um JSON-Daten aus dem public-Verzeichnis zu laden, und gelernt, wie man die vier UI-Zustände einer Anfrage behandelt (Laden/Erfolg/Fehler/Leer).
Jetzt werden die Blogdaten asynchron aus einer externen JSON-Datei geladen, was der Arbeitsweise echter Projekte näher kommt.
Andere Erweiterungen