aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Webentwicklung

Vue Pinia für State-Verwaltung: Abschied von Vuex

vue pinia ist der offizielle und heute empfohlene Weg, gemeinsam genutzten State (Zustand) in Vue-3-Anwendungen zu verwalten. Wenn mehrere Komponenten dieselben Daten brauchen — den angemeldeten Benutzer, den Warenkorb, die Theme-Einstellung — willst du diese an einer zentralen Stelle halten. Der alte Standard dafür war Vuex, doch das Vue-Team empfiehlt für neue Projekte inzwischen Pinia. In diesem Artikel sehen wir Schritt für Schritt, wie man mit Pinia statt mit Vuex einen Store von Grund auf aufbaut.

Warum Pinia statt Vuex?

Pinia ist die offizielle State-Management-Bibliothek, die Vuex ablöst, und sie wird bevorzugt, weil sie einige konkrete Probleme löst:

  • Weniger Zeremonie: In Vuex musstest du mutations schreiben, um etwas zu ändern. Pinia verwirft das Mutation-Konzept vollständig; du änderst den State direkt oder aus den actions heraus.
  • Volle TypeScript-Unterstützung: Typen werden automatisch abgeleitet; this und Rückgabewerte sind ohne zusätzlichen Boilerplate typisiert.
  • Keine Module, nur flache Stores: Statt der verschachtelten Modulstruktur von Vuex ist jeder Store eine eigenständige Einheit. Du rufst jeden Store von überall auf.
  • Für die Composition API gebaut: Pinia arbeitet natürlich mit der setup-Logik von Vue 3 und bringt Devtools-Unterstützung mit.

Kurz gesagt: Pinia macht alles, was Vuex konnte, mit weniger Code und besserer Typsicherheit. Hast du bereits ein Vuex-Projekt, musst du nicht zwanghaft migrieren, aber neue Stores in Pinia zu schreiben ist sinnvoll.

Pinia installieren und registrieren

Installiere zuerst das Paket, erstelle dann mit createPinia() eine Instanz und registriere sie an deiner App:

npm install pinia
// main.js
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";

const app = createApp(App);
app.use(createPinia());
app.mount("#app");

Das ist alles. Du kannst jetzt überall in der App Stores definieren und nutzen. Statt des einen riesigen store-Objekts von Vuex erstellst du mit Pinia mehrere kleine Stores.

Dein erster Store: state, getters und actions

Ein Store wird mit defineStore definiert. Das erste Argument ist eine eindeutige id (die Devtools nutzen sie), das zweite ist der Inhalt des Stores. Hier das klassische Zähler-Beispiel:

// stores/counter.js
import { defineStore } from "pinia";

export const useCounterStore = defineStore("counter", {
  state: () => ({
    count: 0,
    name: "Zähler",
  }),
  getters: {
    double: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++;
    },
    reset() {
      this.count = 0;
    },
  },
});

Du siehst die drei Kernbestandteile:

  • state: eine Funktion, die die Anfangsdaten zurückgibt. Dass es eine Funktion ist, stellt sicher, dass jede Instanz ihren eigenen frischen State erhält.
  • getters: berechnete, aus dem State abgeleitete Werte. Sie werden wie Vues computed zwischengespeichert; hier wird double erst neu berechnet, wenn sich count ändert.
  • actions: Methoden, die den State ändern und deine Geschäftslogik enthalten. Anders als bei Vuex gibt es keine Sync/Async-Trennung; eine Action kann direkt async sein.

Beachte, dass es keinen mutations-Abschnitt wie in Vuex gibt. Wenn du den State ändern willst, schreibst du einfach this.count++ innerhalb einer Action.

Den Store in einer Komponente nutzen

Um einen Store zu nutzen, rufst du ihn innerhalb von setup auf. Das zurückgegebene Objekt ist reaktiv, du kannst es also direkt im Template verwenden:

<script setup>
import { useCounterStore } from "@/stores/counter";

const counter = useCounterStore();
</script>

<template>
  <p>Zähler: {{ counter.count }}</p>
  <p>Doppelt: {{ counter.double }}</p>
  <button @click="counter.increment()">Erhöhen</button>
  <button @click="counter.reset()">Zurücksetzen</button>
</template>

Hier sind counter.count, counter.double und counter.increment() direkt zugänglich. Du liest den State im Template und löst eine Action per Klick aus.

storeToRefs: destrukturieren ohne Reaktivität zu verlieren

Oft willst du ein paar Felder aus dem Store herausziehen und mit kurzen Namen nutzen. Destrukturierst du den Store aber direkt, geht die Reaktivität verloren:

// FALSCH — count ist nicht mehr reaktiv
const { count, double } = useCounterStore();

Der richtige Weg ist, storeToRefs für State und Getter zu verwenden. Dieser Helfer gibt jedes Feld als reaktive ref zurück. Actions können, da sie Funktionen sind, direkt destrukturiert werden:

import { storeToRefs } from "pinia";

const store = useCounterStore();
const { count, double } = storeToRefs(store); // bleibt reaktiv
const { increment, reset } = store;           // Actions direkt entnommen

Asynchrone Actions und gebündelte Updates

In echten Apps machen Actions häufig API-Aufrufe. Anders als bei Vuex brauchst du kein eigenes Konstrukt; mach die Action einfach async:

actions: {
  async fetchUser(id) {
    this.loading = true;
    try {
      const res = await fetch(`/api/users/${id}`);
      this.user = await res.json();
    } finally {
      this.loading = false;
    }
  },
}

Willst du mehrere Felder auf einmal aktualisieren, kannst du $patch verwenden; das wird als eine einzige Änderung verfolgt und sieht in den Devtools sauberer aus:

store.$patch({ count: 10, name: "Neu" });

Du kannst den State mit store.$reset() auch auf seinen Anfangswert zurücksetzen und mit store.$subscribe() jede Änderung mithören (etwa um in den localStorage zu schreiben). Das sind kleine, aber wertvolle Details, die zeigen, wie sehr Pinia die tägliche Arbeit gegenüber Vuex vereinfacht.

Häufige Fragen

Soll ich Pinia oder Vuex verwenden?

Pinia für neue Vue-3-Projekte. Vues offizielle Empfehlung ist nun Pinia, und Vuex befindet sich im Wartungsmodus. Hast du ein großes bestehendes Vuex-Projekt, ist eine dringende Migration nicht nötig, aber neue Funktionen in Pinia zu schreiben ist die zukunftssicherste Wahl.

Warum gibt es in Pinia keine Mutations?

Vuex verlangte Mutations, damit die Devtools Änderungen verfolgen konnten. Da Pinia State-Änderungen direkt verfolgen kann, wurde diese Zwischenschicht überflüssig; du änderst den State innerhalb einer Action oder mit $patch, und die Devtools zeichnen trotzdem jeden Schritt auf.

Können mehrere Stores miteinander kommunizieren?

Ja. Innerhalb der Action oder des Getters eines Stores kannst du einen anderen Store aufrufen: Du rufst die entsprechende useOtherStore()-Funktion auf und nutzt die zurückgegebene Instanz. Stores können sich gegenseitig erreichen, ohne die Modul-Namespace-Komplexität von Vuex.

Eine gut strukturierte State-Architektur ist das Rückgrat einer wachsenden Vue-App. Baust du ein Vue-3-+-Pinia-Projekt oder möchtest du bestehenden Vuex-Code modernisieren, nimm Kontakt mit mir auf — lass uns gemeinsam eine saubere, skalierbare Struktur aufsetzen.

Bu kategorideki tüm yazılar →

Devamı için