Appearance
Kapitel 8: Composables & kompositionelle Logik
In diesem Kapitel lernen Sie, was Composables sind, wie Sie diese erstellen und wie Sie logische Funktionen wiederverwenden.
8.1 Was sind Composables?
Composables sind Vue 3 Composition API-Funktionen, die wiederverwendbare Logik kapseln.
Unterschied: Vue Composables vs. Nuxt Composables
| Merkmal | Vue Composables | Nuxt Composables |
|---|---|---|
| Speicherort | Beliebig (meist composables/) | Automatisch in composables/ |
| Import | Manuell | Auto-Import |
| SSR-Unterstützung | Manuell | Integriert |
| Kontext | Vue-Kontext | Nuxt-Kontext (useNuxtApp) |
In Nuxt 3 werden alle Funktionen im composables/-Verzeichnis automatisch importiert!
8.2 Einfaches Composable erstellen
Beispiel: composables/useCounter.ts
typescript
// Einfaches Composable
export function useCounter() {
const count = ref(0)
const increment = () => {
count.value++
}
const decrement = () => {
count.value--
}
const reset = () => {
count.value = 0
}
return {
count: readonly(count), // Schreibgeschützt exportieren
increment,
decrement,
reset
}
}Verwendung (kein Import erforderlich!):
vue
<!-- pages/index.vue -->
<script setup>
// Kein Import! Nuxt importiert automatisch aus composables/
const { count, increment, decrement, reset } = useCounter()
</script>
<template>
<div>
<h2>Zähler: {{ count }}</h2>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<button @click="reset">Zurücksetzen</button>
</div>
</template>8.3 Integrierte Nuxt Composables
Nuxt 3 bietet viele integrierte Composables:
Wichtigste Composables:
| Composable | Beschreibung |
|---|---|
useRoute() | Aktuelle Route abrufen |
useRouter() | Router-Instanz |
useFetch() | Daten abrufen |
useAsyncData() | Asynchrone Daten |
useState() | Reaktiver Zustand |
useCookie() | Cookies verwalten |
useHead() | Meta-Tags setzen |
useSeoMeta() | SEO-Meta-Tags |
useRuntimeConfig() | Laufzeit-Konfiguration |
Beispiel: useRoute() verwenden
vue
<script setup>
const route = useRoute()
const router = useRouter()
// Auf Route-Parameter zugreifen
const postId = route.params.id
// Programmatisch navigieren
const goToHome = () => {
router.push('/')
}
</script>8.4 Benutzerdefinierte Composables (Fortgeschritten)
Beispiel 1: useFetchPosts.ts (Datenabfrage kapseln)
typescript
// composables/useFetchPosts.ts
export function useFetchPosts() {
const posts = ref([])
const pending = ref(false)
const error = ref(null)
const fetchPosts = async () => {
pending.value = true
error.value = null
try {
const data = await $fetch('/api/posts')
posts.value = data
} catch (err) {
error.value = err
} finally {
pending.value = false
}
}
// Beim Erstellen sofort abrufen
onMounted(() => {
fetchPosts()
})
return {
posts: readonly(posts),
pending: readonly(pending),
error: readonly(error),
fetchPosts
}
}Verwendung:
vue
<script setup>
const { posts, pending, error, fetchPosts } = useFetchPosts()
</script>
<template>
<div>
<div v-if="pending">Lädt...</div>
<div v-else-if="error">Fehler!</div>
<ul v-else>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
<button @click="fetchPosts">Aktualisieren</button>
</div>
</template>Beispiel 2: useWindowSize.ts (Browser-API kapseln)
typescript
// composables/useWindowSize.ts
export function useWindowSize() {
const width = ref(0)
const height = ref(0)
const updateSize = () => {
if (process.client) {
width.value = window.innerWidth
height.value = window.innerHeight
}
}
onMounted(() => {
updateSize()
window.addEventListener('resize', updateSize)
})
onUnmounted(() => {
if (process.client) {
window.removeEventListener('resize', updateSize)
}
})
return {
width: readonly(width),
height: readonly(height)
}
}Verwendung:
vue
<script setup>
const { width, height } = useWindowSize()
</script>
<template>
<div>
<p>Fensterbreite: {{ width }}px</p>
<p>Fensterhöhe: {{ height }}px</p>
</div>
</template>8.5 Composables-Verzeichnisstruktur
Für größere Projekte sollten Sie Composables strukturieren:
composables/
├── useCounter.ts # Einfache Composables
├── useFetchPosts.ts
├── useWindowSize.ts
├── auth/ # Auth-bezogene Composables
│ ├── useAuth.ts
│ ├── useUser.ts
│ └── usePermissions.ts
├── posts/ # Post-bezogene Composables
│ ├── usePosts.ts
│ └── usePostDetail.ts
└── utils/ # Hilfs-Composables
├── useFormatDate.ts
└── useDebounce.ts8.6 Best Practices für Composables
1. Immer readonly() für zurückgegebene Refs verwenden
typescript
export function useCounter() {
const count = ref(0)
return {
count: readonly(count), // Verhindert externe Mutationen
increment: () => count.value++
}
}2. Asynchrone Logik mit useAsyncData() kombinieren
typescript
export function usePosts() {
const { data, pending, error, refresh } = useAsyncData(
'posts',
() => $fetch('/api/posts')
)
return {
posts: data,
pending,
error,
refresh
}
}3. Auf SSR-Kontext achten
typescript
export function useClientOnly() {
const isClient = ref(false)
onMounted(() => {
isClient.value = true
})
return { isClient }
}8.7 Zusammenfassung
In diesem Kapitel haben Sie gelernt:
- ✅ Was Composables sind (Vue 3 Composition API-Funktionen)
- ✅ Den Unterschied zwischen Vue- und Nuxt-Composables
- ✅ Eigene Composables im
composables/-Verzeichnis zu erstellen - ✅ Nuxt's Auto-Import-Mechanismus zu nutzen
- ✅ Fortgeschrittene Composables (Datenabfrage, Browser-APIs)
- ✅ Best Practices für Composables
Nächste Schritte: Im nächsten Kapitel lernen wir SSR (Server-Side Rendering) & SSG (Static Site Generation) – die leistungsstarken Rendering-Modi von Nuxt.
📚 Weiterführende Ressourcen
Nächstes Kapitel: Kapitel 9: SSR & SSG →
