Appearance
Kapitel 18: Komponenten-Kommunikation (Teil 3) - Provide & Inject
📙 Lernziel: Daten von Vorfahren zu Nachkommen mit provide() und inject() weitergeben!
18.1 Was sind Provide & Inject?
Problem: Props mehrfach weitergeben ("Prop Drilling").
Lösung: provide() und inject() - Daten direkt an Nachkommen weitergeben.
Datenfluss: Vorfahre → Alle Nachkommen (überspringt Zwischenkomponenten)
Beispiel-Szenario:
App.vue (Vorfahre)
└─ Layout.vue (Zwischenkomponente - braucht Props nicht)
└─ Sidebar.vue (Nachkomme)
Erhält Daten direkt von App.vue18.2 provide() in Vorfahre
provide() stellt Daten für alle Nachkommen bereit.
Syntax:
javascript
import { provide } from 'vue'
provide(schlüssel, wert)Beispiel:
vue
<!-- App.vue (Vorfahre) -->
<script setup>
import { provide, ref } from 'vue'
import Layout from './components/Layout.vue'
// Daten bereitstellen
const theme = ref('light')
const user = ref({ name: 'Max', role: 'admin' })
provide('theme', theme)
provide('user', user)
</script>
<template>
<div :class="`theme-${theme}`">
<h1>Meine App</h1>
<Layout />
</div>
</template>18.3 inject() in Nachkomme
inject() ruft bereitgestellte Daten ab.
Syntax:
javascript
import { inject } from 'vue'
const wert = inject(schlüssel, fallbackWert)Beispiel:
vue
<!-- Sidebar.vue (Nachkomme) -->
<script setup>
import { inject, ref } from 'vue'
// Daten abrufen
const theme = inject('theme')
const user = inject('user')
const nonExistent = inject('nicht-existent', 'Standardwert')
</script>
<template>
<div class="sidebar">
<p>Aktuelles Theme: {{ theme }}</p>
<p>Benutzer: {{ user.name }} ({{ user.role }})</p>
</div>
</template>Wichtig:
- ✅ Nachkommen können bereitgestellte Daten ändern (Vorsicht!)
- ✅ Änderungen sind reaktiv
18.4 Reaktive Provide/Inject (Best Practice)
Problem: Nachkommen sollten Provide-Daten nicht direkt ändern.
Lösung: Funktionen bereitstellen, um Daten zu ändern.
Beispiel:
vue
<!-- App.vue (Vorfahre) -->
<script setup>
import { provide, ref } from 'vue'
const theme = ref('light')
// Funktion bereitstellen
const toggleTheme = () => {
theme.value = theme.value === 'light' ? 'dark' : 'light'
}
provide('theme', theme)
provide('toggleTheme', toggleTheme)
</script>
<template>
<div :class="`theme-${theme}`">
<h1>Meine App</h1>
<button @click="toggleTheme">Theme wechseln</button>
<Layout />
</div>
</template>Verwendung in Nachkomme:
vue
<!-- Sidebar.vue (Nachkomme) -->
<script setup>
import { inject } from 'vue'
const theme = inject('theme')
const toggleTheme = inject('toggleTheme')
</script>
<template>
<div class="sidebar">
<p>Theme: {{ theme }}</p>
<button @click="toggleTheme">Wechseln</button>
</div>
</template>18.5 Symbol als Schlüssel (Beste Praxis)
Problem: String-Schlüssel können kollidieren.
Lösung: Symbol als Schlüssel verwenden.
Beispiel:
javascript
// keys.js (separate Datei)
export const THEME_KEY = Symbol('theme')
export const USER_KEY = Symbol('user')vue
<!-- App.vue -->
<script setup>
import { provide, ref } from 'vue'
import { THEME_KEY, USER_KEY } from './keys.js'
const theme = ref('light')
const user = ref({ name: 'Max' })
provide(THEME_KEY, theme)
provide(USER_KEY, user)
</script>vue
<!-- Sidebar.vue -->
<script setup>
import { inject } from 'vue'
import { THEME_KEY, USER_KEY } from '../keys.js'
const theme = inject(THEME_KEY)
const user = inject(USER_KEY)
</script>18.6 Übung: Einfacher State Management
Aufgabe: Erstelle einen einfachen State Management mit provide/inject.
Lösung:
vue
<!-- App.vue -->
<script setup>
import { provide, ref, computed } from 'vue'
import Layout from './components/Layout.vue'
// State
const todos = ref([
{ id: 1, text: 'Lernen', done: false },
{ id: 2, text: 'Sport', done: true }
])
// Actions
const addTodo = (text) => {
todos.value.push({
id: Date.now(),
text,
done: false
})
}
const removeTodo = (id) => {
todos.value = todos.value.filter(todo => todo.id !== id)
}
const toggleTodo = (id) => {
const todo = todos.value.find(t => t.id === id)
if (todo) todo.done = !todo.done
}
// Computed
const doneCount = computed(() => todos.value.filter(t => t.done).length)
// Bereitstellen
provide('todos', todos)
provide('addTodo', addTodo)
provide('removeTodo', removeTodo)
provide('toggleTodo', toggleTodo)
provide('doneCount', doneCount)
</script>
<template>
<div>
<h1>To-Do App</h1>
<Layout />
</div>
</template>Verwendung in Nachkomme:
vue
<!-- TodoList.vue -->
<script setup>
import { inject, computed } from 'vue'
const todos = inject('todos')
const addTodo = inject('addTodo')
const removeTodo = inject('removeTodo')
const toggleTodo = inject('toggleTodo')
const doneCount = inject('doneCount')
const newTodo = ref('')
</script>
<template>
<div>
<input v-model="newTodo" @keyup.enter="addTodo(newTodo); newTodo = ''" />
<button @click="addTodo(newTodo); newTodo = ''">Hinzufügen</button>
<ul>
<li v-for="todo in todos" :key="todo.id">
<input type="checkbox" :checked="todo.done" @change="toggleTodo(todo.id)" />
<span :style="{ textDecoration: todo.done ? 'line-through' : 'none' }">
{{ todo.text }}
</span>
<button @click="removeTodo(todo.id)">Löschen</button>
</li>
</ul>
<p>Erledigt: {{ doneCount }}</p>
</div>
</template>✅ Zusammenfassung
In diesem Kapitel hast du gelernt:
- ✅ Was
provide/injectsind (Lösung für Prop Drilling) - ✅
provide()in Vorfahre nutzen - ✅
inject()in Nachkomme nutzen - ✅ Reaktive Provide/Inject (Best Practice)
- ✅ Symbol als Schlüssel (Beste Praxis)
- ✅ Praxis: Einfacher State Management
🎯 Nächster Schritt: In Kapitel 19 lernst du Komponenten-Slots!
