Skip to content

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 mutations mehr

Vergleich:

MerkmalVuexPinia
TypeScriptSchwerEinfach
APIKomplexEinfach
ModulleNamespacedAutomatisch
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 →

Frei für alle Anfänger