Vue.js unter der Lupe: VueX
VueX ist die offizielle Bibliothek für das State Management in Vue.js. VueX ist dazu da, Daten zwischen den Komponenten einer Anwendung zu teilen. Vue-Komponenten können out-of-the-box auf zwei Arten kommunizieren:
- Per Props, um den Zustand einer Parent-Komponente an eine Child-Komponente zu übergeben
- Events, um den Zustand einer Parent-Komponente von einer Child-Komponente aus zu verändern oder indem die Root-Komponente als Event Bus benutzt wird
Manchmal werden die Dinge jedoch komplexer als das, was diese simplen Optionen zulassen. In diesem Fall ist es eine gute Option, den Zustand in einem Store zu zentralisieren. Genau das ist es auch, was Vue macht.
Dossier Vue.js
In unserem Themendossier Vue.js nehmen wir das neue JavaScript-Framework genau unter die Lupe. Bisher erschienen:
- Das Vue.js Tutorial zum Mitmachen: Teil 1 – Einordnung und Überblick
- Das Vue.js Tutorial zum Mitmachen: Teil 2 – Komponenten mit Vue.js entwickeln
- Vue.js unter der Lupe: Kommunikation zwischen Komponenten
- Video: Vue und VueX – Anwendungen im Team skalieren
- Interview: State-Management in JavaScript: Was kann VueX?
- Vue auf dem Desktop: Wenn das Webframework mit Electron fremdgeht
- Spring Boot und Vue.js im eigenen Projekt praktisch nutzen
- Vue, Angular und React: To-dos mit feinem Unterschied
- Vue.js unter der Lupe: VueX
Vue.js unter der Lupe: Warum Sie VueX einsetzen sollten
VueX ist nicht die einzige Option für das State Management, die man mit Vue verwenden kann (Redux ist auch möglich). Der größte Vorteil an VueX ist aber, dass es die offizielle Option ist und vor allem durch seine Integration mit Vue hervorsticht. Bei React ist das Problem hingegen, dass man sich selbst für eine Option entscheiden muss, da das Ökosystem sehr groß ist und de facto keinen Standard besitzt. In letzter Zeit war Redux jedoch die beliebteste Wahl, gefolgt von MobX, im Hinblick auf die Beliebtheit. Bezüglich Vue würde ich aber sogar so weit gehen zu sagen, dass man sich nach keiner Alternative zu VueX umsehen muss, vor allem nicht zu Beginn.
Vuex hat viele seiner Ideen von dem Ökosystem Reacts übernommen: Das Flux-Pattern, das durch Redux beliebt wurde. Sollten Sie sich bereits mit Flux oder Redux auskennen, so wird Ihnen VueX sehr vertraut sein. Und sollte das nicht der Fall sein, kein Problem – ich werde jedes der Konzepte von Grund auf erklären.
Komponenten in einer Vue-Applikation können einen eigenen Zustand haben. Zum Beispiel speichert ein Eingabefeld die dort eingefügten Daten lokal. Das funktioniert sehr gut; Komponenten können auch bei Verwendung von VueX einen lokalen Zustand haben. Wenn man viel Aufwand betreiben muss um Zustände weiter zu geben, weiß man, dass man VueX braucht. VueX stellt für diesen Anwendungsfall ein zentrales Repository für den Zustand zur Verfügung. Zustände werden verändert, indem man den Store dazu aufordert, das zu machen. Alle Komponenten, die von einem bestimmten Zustand abhängig sind, greifen darauf über Getter zu, der sicherstellt, dass die Komponente aktualisiert wird, sobald sich etwas verändert.
VueX fügt Anwendungen etwas Komplexität hinzu, weil es ein spezifisches Setup benötigt damit alles richtig funktioniert. Wenn VueX aber dabei hilft, das Problem der unorganisierten Übergabe von Props zu lösen und das Event-System zu organisieren, das sonst zu Spaghetti-Code werden kann, wenn es zu kompliziert wird, ist es eine gute Wahl.
State Management mit VueX: Los geht’s!
In diesem Beispiel beginne ich mit einer Vue CLI-Applikation. VueX kann ebenfalls direkt über ein Script-Tag geladen und genutzt werden. Da VueX aber eher auf größere Applikationen ausgelegt ist, ist es wahrscheinlicher, dass es in einer stärker strukturierten App zur Anwendung kommt, die man mit dem Vue CLI aufsetzen kann.
Die Beispiele, die ich hier verwende, sind in CodeSandbox geschrieben, einem großartigen Service, der ein einsatzbereites Vue CLI-Beispiel unter https://codesandbox.io/s/vue anbietet. Ich empfehle, damit herumzuspielen.
Sobald Sie das Beispiel geöffnet haben, klicken Sie auf die Add dependency-Schaltfläche, geben „vuex“ ein und klicken es an. Jetzt wird VueX als Dependency aufgelistet.
Um VueX lokal zu installieren, können Sie einfach npm install vue
oder yarn add vuex
innerhalb des Projektordners ausführen.
VueX Store erstellen
Jetzt können wir unseren VueX Store erstellen.
Diese Datei kann überall abgelegt werden. Im allgemeinen wird empfohlen, sie in der src/store/store.js
-Datei abzulegen, also machen wir das auch einfach.
Wir initialisieren VueX in dieser Datei und sagen dann zu Vue, dass es damit arbeiten soll:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({})
Wir exportieren ein VueX Store-Objekt, das wir mit der Vuex.Store()
-API erstellt haben.
Ein Anwendungsfall für den Store
Jetzt, da wir ein Grundgerüst an Ort und Stelle haben, denken wir uns einen guten Anwendungsfall für VueX aus um die Konzepte einzuführen.
Ich nehme beispielsweise zwei Geschwisterkomponenten, eine mit einem Eingabefeld und eine, die den Inhalt des Eingabefelds ausgibt.
Wenn das Eingabefeld verändert wird, dann möchte ich auch den Inhalt in dieser zweiten Komponente verändern. Das ist sehr simpel, aber völlig ausreichend für unsere Aufgabe.
Erstellen der benötigten Komponenten
Ich lösche die HelloWorld-Komponente und füge eine Formular-Komponente und eine Display-Komponente ein.
<template> <div> <label for="flavor">Favorite ice cream flavor?</label> <input name="flavor"> </div> </template>
<template> <div> <p>You chose ???</p> </div> </template>
Einfügen dieser Komponenten zu der Applikation
Wir fügen sie dem App.vue-Code hinzu, statt der HelloWorld
-Komponente:
<template> <div id="app"> <Form/> <Display/> </div> </template> <script> import Form from './components/Form' import Display from './components/Display' export default { name: 'App', components: { Form, Display } } </script>
Den Zustand zum Store hinzufügen
Jetzt, da alles an seinem Platz ist, gehen wir zurück zu der store.js-Datei und fügen dem Store eine Eigenschaft hinzu, die state
genannt wird und ein Objekt ist, das die flavor
-Eigenschaft beinhaltet. Anfangs ist das ein leerer String.
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ state: { flavor: '' } })
Es wird aktualisiert, wenn der Benutzer in das Eingabefeld schreibt.
Eine Mutation hinzufügen
Der Zustand kann nicht manipuliert werden, außer es werden Mutationen eingesetzt. Wir stellen eine Mutation bereit, die in der Formular-Komponente benutzt wird, um den Store darüber zu benachrichtigen, dass der Zustand verändert werden soll.
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ state: { flavor: '' }, mutations: { change(state, flavor) { state.flavor = flavor } } })
Getter hinzufügen, um eine Zustandseigenschaft zu referenzieren
Nachdem das eingerichtet ist, müssen wir einen Weg hinzufügen, um den Zustand einzusehen. Das machen wir, indem wir getters
benutzen. Wir richten daher ein getter
für die flavor
-Eigenschaft ein:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export const store = new Vuex.Store({ state: { flavor: '' }, mutations: { change(state, flavor) { state.flavor = flavor } }, getters: { flavor: state => state.flavor } })
Beachten Sie, dass getters
ein Objekt ist. flavor
ist eine Eigenschaft dieses Objektes, die den Zustand als Parameter akzeptiert und die flavor
-Eigenschaft des Zustands zurückgibt.
Vue Store zur App hinzufügen
Der Store ist jetzt bereit für die Verwendung. Wir gehen zurück zu unseren Applikationscode und müssen den Status in der main.js-Datei importierten und in unserer Vue Applikation verfügbar machen.
Wir fügen folgendes hinzu:
import { store } from './store/store'
Zur Vue-Anwendung wird das so hinzugefügt:
new Vue({ el: '#app', store, components: { App }, template: '' })
Da dies die wichtigste Vue-Komponente ist, wird die store
-Variable in jeder Vue-Komponente auf den VueX Store zeigen, sobald wird das erledigt haben.
Den Zustand einer User-Aktion mit Commit aktualisieren
Jetzt wollen wir den Status aktualisieren, wenn ein Nutzer etwas tippt.
Das machen wir, indem wir das store.commit
-API benutzen.
Aber zuerst erstellen wir eine Methode, die aufgerufen wird, wenn sich der Inhalt der Eingabe verändert. Wir benutzen dafür @input
, nichtchange
, da letzteres nur dann aktiviert wird, wenn der Fokus von dem Eingabefeld wegbewegt wird, während @input
bei jedem Tastendruck aufgerufen wird.
<template> <div> <label for="flavor">Favorite ice cream flavor?</label> <input @input="changed" name="flavor"> </div> </template> <script> export default { methods: { changed: function(event) { alert(event.target.value) } } } </script>
Jetzt, da wir den Wert von flavor haben, benutzen wir das VueX-API:
<script> export default { methods: { changed: function(event) { this.$store.commit('change', event.target.value) } } } </script>
Sehen Sie, wie wir den Store mit this.$store
referenzieren? Das ist darum möglich, weil das Store-Objekt in der Initialisierung der Vue-Hauptkomponente enthalten ist.
Die commit()
-Methode akzeptiert einen Mutation Name (wir haben change
im Vue Store benutzt) und einen Payload, der als zweiter Paramter für die Callback-Funktion an die Mutation weitergegeben wird.
Getter benutzen, um die Statuswerte zu drucken
Jetzt müssen wie den getter
dieses Wertes in der Darstellungsvorlage referenzieren, indem wir $store.getters.flavor
benutzen. this
kann entfernt werden, da wir in der Vorlage sind und da this
implizit ist.
<template> <div> <p>You chose {{ $store.getters.flavor }}</p> </div> </template>
Vue.js unter der Lupe: VueX – Fazit
Das war’s auch schon mit der Einführung zu VueX!
Der vollständige, funktionierende Quellcode ist unter https://codesandbox.io/s/zq7k7nkzkm verfügbar.
Es fehlen immer noch viele Konzepte in diesem Puzzel:
- Aktionen
- Module
- Helfer
- Plug-Ins
Aber Sie haben die Grundlagen zum weiterarbeiten und können alles andere ja auch in den offiziellen Dokumenten nachlesen.
Frohes Coden!
Dieser Artikel erschien zuerst im Vue Handbuch von Flavio Copes.
Deep Dive im April
Das Online-Camp für fortgeschrittene Angular-Entwickler:innen.
Basic Camp im Juni
Lerne Angular Schritt für Schritt.