Appearance
Kapitel 33: Pinia Grundlagen
📙 Lernziel: Pinia installieren und Grundlagen verstehen!
33.1 Was ist Pinia?
Pinia ist das offizielle State-Management für Vue 3 (Nachfolger von Vuex).
Vorteile gegenüber Vuex:
- ✅ TypeScript-Unterstützung
- ✅ Einfachere API
- ✅ Bessere Modul-Archtitektur
- ✅ Kein
mutationsmehr
Vergleich:
| Merkmal | Vuex | Pinia |
|---|---|---|
| TypeScript | Schwer | Einfach |
| API | Komplex | Einfach |
| Modulle | Namespaced | Automatisch |
| Mutations | ✅ Ja | ❌ Nein |
33.2 Pinia installieren
Installation:
bash
# Mit pnpm (empfohlen)
pnpm add pinia
# Mit npm
npm install pinia
# Mit yarn
yarn add piniaÜberprüfung (package.json):
json
{
"dependencies": {
"vue": "^3.4.0",
"pinia": "^2.1.0"
}
}33.3 Pinia in Vue App registrieren
main.js konfigurieren:
javascript
// src/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
// Pinia erstellen
const pinia = createPinia()
createApp(App)
.use(pinia) // Pinia registrieren
.mount('#app')Wichtig:
- ✅
createPinia()erstellen - ✅
.use(pinia)registrieren
33.4 Erstes Store erstellen
Store-Datei erstellen (src/stores/counter.js):
javascript
// src/stores/counter.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
// State (reaktiv)
const count = ref(0)
// Getters (computed)
const doubleCount = computed(() => count.value * 2)
// Actions (Methoden)
const increment = () => {
count.value++
}
const decrement = () => {
count.value--
}
const reset = () => {
count.value = 0
}
return {
count,
doubleCount,
increment,
decrement,
reset
}
})Erklärung:
- ✅
defineStore()- Store definieren - ✅ Erster Parameter: Store-Name (eindeutig)
- ✅ Zweiter Parameter: Setup-Funktion (Composition API Stil)
33.5 Store in Komponente verwenden
Beispiel (Counter.vue):
vue
<!-- src/components/Counter.vue -->
<script setup>
import { useCounterStore } from '../stores/counter'
// Store verwenden
const counterStore = useCounterStore()
</script>
<template>
<div class="counter">
<h2>Zähler: {{ counterStore.count }}</h2>
<p>Doppelt: {{ counterStore.doubleCount }}</p>
<button @click="counterStore.increment()">+</button>
<button @click="counterStore.decrement()">-</button>
<button @click="counterStore.reset()">Zurücksetzen</button>
</div>
</template>
<style scoped>
.counter {
border: 1px solid #42b883;
border-radius: 8px;
padding: 20px;
max-width: 400px;
margin: 0 auto;
}
button {
margin: 0 5px;
padding: 5px 15px;
background: #42b883;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>Wichtig:
- ✅ Store importieren:
import { useCounterStore } from '../stores/counter' - ✅ Store-Instanz erstellen:
const counterStore = useCounterStore() - ✅ State/Getters/Actions direkt verwenden:
counterStore.count
33.6 Store mit setup() Syntax (Options Stil)
Alternative: Options API Stil:
javascript
// src/stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
// State
state: () => ({
count: 0
}),
// Getters
getters: {
doubleCount: (state) => state.count * 2
},
// Actions
actions: {
increment() {
this.count++
},
decrement() {
this.count--
},
reset() {
this.count = 0
}
}
})Unterschied:
- Setup Stil (empfohlen): Composition API, TypeScript-freundlich
- Options Stil: Vuex-ähnlich, für Vuex-Umsteiger
33.7 Übung: Todo Store mit Pinia
Aufgabe: Erstelle einen Todo Store mit Pinia.
Lösung:
1. Store erstellen (src/stores/todo.js):
javascript
// src/stores/todo.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useTodoStore = defineStore('todo', () => {
// State
const todos = ref([
{ id: 1, text: 'Lernen', done: false },
{ id: 2, text: 'Sport', done: true }
])
// Getters
const doneTodos = computed(() => todos.value.filter(todo => todo.done))
const undoneTodos = computed(() => todos.value.filter(todo => !todo.done))
// 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
}
return {
todos,
doneTodos,
undoneTodos,
addTodo,
removeTodo,
toggleTodo
}
})2. Komponente erstellen (TodoList.vue):
vue
<!-- src/components/TodoList.vue -->
<script setup>
import { ref } from 'vue'
import { useTodoStore } from '../stores/todo'
const todoStore = useTodoStore()
const newTodo = ref('')
const addTodo = () => {
if (newTodo.value.trim() !== '') {
todoStore.addTodo(newTodo.value)
newTodo.value = ''
}
}
</script>
<template>
<div class="todo-list">
<h2>Todo Liste</h2>
<div>
<input
v-model="newTodo"
@keyup.enter="addTodo()"
placeholder="Neue Aufgabe..."
/>
<button @click="addTodo()">Hinzufügen</button>
</div>
<ul>
<li v-for="todo in todoStore.todos" :key="todo.id">
<input
type="checkbox"
:checked="todo.done"
@change="todoStore.toggleTodo(todo.id)"
/>
<span :style="{ textDecoration: todo.done ? 'line-through' : 'none' }">
{{ todo.text }}
</span>
<button @click="todoStore.removeTodo(todo.id)">Löschen</button>
</li>
</ul>
<p>Erledigt: {{ todoStore.doneTodos.length }}</p>
<p>Offen: {{ todoStore.undoneTodos.length }}</p>
</div>
</template>
<style scoped>
.todo-list {
max-width: 500px;
margin: 0 auto;
padding: 20px;
}
button {
margin: 0 5px;
padding: 5px 10px;
background: #42b883;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
li {
margin: 10px 0;
}
</style>✅ Zusammenfassung
In diesem Kapitel hast du gelernt:
- ✅ Was Pinia ist (State Management für Vue 3)
- ✅ Pinia installieren
- ✅ Pinia in Vue App registrieren
- ✅ Erstes Store erstellen (Setup Stil)
- ✅ Store in Komponente verwenden
- ✅ Store mit Options Stil (Alternative)
- ✅ Praxis: Todo Store mit Pinia
🎯 Nächster Schritt: In Kapitel 34 lernst du State, Getters & Actions in Pinia!
← Zurück zu Kapitel 32: Route-GuardsWeiter zu Kapitel 34: State, Getters & Actions →
