Frontend-Anwendungen, vor allem die komplexeren, müssen eine Menge Daten verarbeiten. Programmierer führen verschiedene Entwurfsmuster ein, um ihre Projekte lesbar und wartbar zu machen. In den meisten der üblichen Szenarien, in denen wir mit MVC arbeiten, wollen wir die Daten von den visuellen Teilen der Anwendung trennen.
Das ist der Grund, warum speichern so nützlich geworden ist. Es liegt an Ihnen, ob Sie React + Redux verwenden oder Vue + Vuex - das Hauptziel ist das gleiche, nämlich Ihre Daten strukturiert, zugänglich und gleichzeitig sicher zu halten.
In diesem Artikel zeige ich Ihnen ein paar Beispiele, wie Sie Ihren Vuex-Speicher sauber und effizient halten können.
Bevor wir beginnen, lassen Sie uns davon ausgehen, dass:
- Sie haben einige Erfahrung mit modernen JavaScript,
- Sie wissen grundsätzlich, was Vue ist und wie man es verwendet Requisiten, errechnet, usw.,
- Sie sind vertraut mit Vuex (Aktionen, Mutationen, usw.) und wollen Ihre Anwendungen verbessern.
Vuexwie die Mehrheit der zentralen Vue-Projekteist ziemlich gut dokumentiert und Sie können viele nützliche Hacks in den offiziellen Dokumenten finden. Wir haben einige wichtige Informationen daraus für Sie extrahiert.
Eine einfache Vuex-Speicherimplementierung sieht wie folgt aus:
// main.js
importiere Vue von 'vue'
importieren Vuex von 'vuex'; importieren Vuex von 'vuex
importiere App von "./App";
Vue.use(Vuex)
const store = new Vuex.Store((
Zustand: (
data: null;
),
actions: (
someAction: (( commit ), data) (
commit("SOME_MUTATION", data);
)
),
Mutationen: (
SOME_MUTATION (state, data) (
state.data = data;
)
))
));
new Vue((
el: "#app",
render: h => h(App),
speichern:
));
Wenn Ihre Anwendung größer wird, müssen Sie normalerweise Routing, einige globale Direktiven, Plugins usw. anwenden. Das macht die main.js
Datei viel länger und schwieriger zu lesen. Es ist eine gute Praxis, den Speicher in einer externen Datei zu speichern, wie hier:
// store.js
importieren Vue von 'vue'
importiere Vuex von 'vuex'
Vue.use(Vuex);
const state = (
data: null;
);
const actions = (
someAction: (( commit ), data) (
commit("SOME_MUTATION", data);
)
);
const mutations = (
SOME_MUTATION (state, data) (
state.data = data;
)
);
export default new Vuex.Store((
Zustand,
Aktionen,
Mutationen
));
1. Module
Was sollten Sie tun, wenn die store.js
Datei riesig wird und schwer zu bearbeiten ist? Tatsächlich gibt es eine wirklich coole Funktion des Vuex - Module. Sie dienen dazu, Ihre Daten in separate Dateien aufzuteilen.
Stellen Sie sich vor, Sie arbeiten an einer Unternehmensanwendung, in der Sie z. B. nur wenige Datenbereiche haben:
- Benutzer (Verwaltung aller Autorisierungen und Berechtigungen),
- Routenparameter (Verwaltung globaler Parameter vor Anfragen an die API),
- Umsatz (für Ihre SalesMegaChart-Komponente, die in einem monatlichen/quartalsweisen/jährlichen Kontext sichtbar ist),
- Aufträge (sichtbar nach Anklicken der SalesMegaChart-Leiste).
...und vielleicht noch ein paar mehr. Jetzt haben Sie ernsthafte Gründe, eine gewisse Modularität in Ihrem Geschäft einzuführen.
Verschieben Sie zunächst die store.js
Datei in eine neu erstellte speichern/
Verzeichnis und benennen Sie es um in index.js
. Wenn Sie alles in Module verpacken möchten, können Sie optional die Staat, Aktionen und Mutationen aus der Hauptdatei.
// store/index.js
importiere Vue von 'vue'
importiere Vuex von 'vuex'
Vue.use(Vuex);
export default new Vuex.Store((
Module: (
// Module werden hier abgelegt
)
));
Dann erstellen Sie neben der Datei "store/index.js" das erste Modul - "store/user.js".
import ApiService from '../services/api.service';
const state = (
loggedIn: false,
loginError: null,
Benutzer: null
);
const actions = (
login: async (( commit ), data) (
try (
const response = await ApiService.post('/login', data);
const ( user ) = response.data;
COMMIT("SAVE_USER", user);
COMMIT("LOGIN_SUCCESS");
) catch (Fehler) (
commit("LOGIN_ERROR", Fehler);
)
)
);
constations = (
SAVE_USER (state, user) (
state.user = user;
),
LOGIN_SUCCESS (state) (
state.loggedIn = true;
),
LOGIN_ERROR (state, error) (
state.loginError = error;
state.loggedIn = false;
)
);
export const user (
state,
Aktionen,
Mutationen
)
Und nun laden Sie das fertige Modul in die Hauptdatei "store/index.js":
import Vue von 'vue'
importiere Vuex von 'vuex'
import ( user ) from './user';
Vue.use(Vuex);
export default new Vuex.Store((
Module: (
Benutzer
)
));
Herzlichen Glückwunsch! Jetzt haben Sie eine wirklich hübsche Speicherimplementierung. Sie können auch auf die Daten aus der Komponente zugreifen (z.B., BenutzerProfil.vue
) wie folgt:
<template>
<div class="user-profile">
<h2>(( user.name )))!</h2>
<!-- component template goes here -->
</div>
</template>
<script> import ( mapActions ) from 'Vuex';
export default (
name: 'UserProfile',
computed: mapState((
user: state => state.user
// user: 'user' <-- alternative syntax
))
)
</script>
2. Namespaces
Nachdem Sie nun wissen, wie Sie die Module verwenden, sollten Sie sich auch mit den Funktionen des Vuex vertraut machen Namespacing. Im vorherigen Schritt haben wir die store/user.js
Datei mit der Benutzer Modul.
Die Datenstruktur, die in der Datei user.js
Datei von den Komponenten aus zugänglich ist, aber Sie können feststellen, dass alle Benutzer Daten gehen direkt an die globale Staat
Kontext, wie hier:
berechnet: mapState((
user: state => state.user
// user: 'user' <-- alternativer Weg
))
Wenn Sie mehr Module definieren, werden Sie wahrscheinlich verwirrt sein, welches Objekt von welchem Modul stammt. Dann sollten Sie Module mit Namensräumen verwenden und sie auf diese Weise definieren:
export const user (
namespaced: true, // <-- namespacing!
state,
actions,
mutations:
)
Von nun an werden alle Ihre Benutzer Daten (Staat
variabel von store/user.js
Datei) wird unter der status.benutzer
Hinweis:
berechnet: mapState((
user: state => state.user.user
// user: 'user/user' <-- alternativer Weg
))
Ein paar Schritte später können Sie für die Komponente etwas wie dieses erreichen:
import ( mapActions ) from 'Vuex';
export default (
name: 'Dashboard',
berechnet: mapState((
sales: 'sales/data',
orders: 'orders/data',
sortBy: 'aufträge/sortBy',
loggedIn: 'user/loggedIn'
)),
methods: mapActions((
logout: 'user/logout',
loadSales: 'sales/load',
loadOrders: 'Bestellungen/Laden'
)),
created() (
if (this.loggedIn) (
loadSales();
loadOrders();
)
)
)
Bravo! So frisch, so sauber... Aber keine Sorge, das Refactoring hört nie auf. Sind Sie bereit für die nächsten Schritte?
3. Kommunikation zwischen Modulen
Im ersten Schritt haben Sie einige Aktionen in der Benutzer Modul:
const actions = (
login: async (( commit ), data) (
try (
const response = await ApiService.post('/login', data);
const ( user ) = response.data;
COMMIT("SAVE_USER", user);
COMMIT("LOGIN_SUCCESS");
) catch (Fehler) (
commit("LOGIN_ERROR", Fehler);
)
)
);
Im Falle eines Scheiterns fügen wir einen Anmeldefehler in unseren Shop ein - was kommt als nächstes?
Hier gibt es mehrere Möglichkeiten, und die Wahl hängt davon ab, welche Option Ihren Bedürfnissen besser entspricht. Die einfachste Möglichkeit ist die Verwendung der v-if
Direktive, dank derer eine Fehlermeldung angezeigt werden kann, wenn in Ihrem Shop ein Fehler auftritt.
<template>
<div class="dashboard">
<!-- dashboard component template -->
<div
v-if="error"
class="error-message"
> (( error.message )) </div>
</div>
</template>
<script> import ( mapActions ) from 'Vuex';
export default (
name: 'Dashboard',
computed: mapState((
error: "user/loginError"
))
)
</script>
Stellen Sie sich wieder vor, Sie haben viele Module und jedes try/catch
Syntax erzeugt einen neuen Fehler in Ihrem Shop. Offensichtlich werden Sie die DRY-Regel auf diese Weise missbrauchen.
Wie können Sie Ihre Fehlerbehandlungsprozesse generischer gestalten?
Definieren wir die gemeinsame Modul und fügen Sie dort eine Logik ein, die global verwendet werden soll.
// store/common.js
const state = (
errors: []
);
const actions = (
Fehler: (
root: true,
handler(( commit ), error) (
commit("ERROR", error);
)
)
),
const mutations = (
ERROR (state, error) (
/* auf diese Weise steht der neueste Fehler ganz oben in der Liste */
state.errors = [error, ...state.errors];
))
);
export const common (
namespaced: true,
Zustand,
Mutationen
)
Jetzt können wir die Benutzer Modul (und auch andere Module):
try (
// irgendeine Aktion
)catch (error) (
commit("common/ERROR", error, ( root: true ));
)
oder auf elegantere Weise mit unserer globalen Aktion:
try (
// irgendeine Aktion
) catch (Fehler) (
dispatch("Fehler", Fehler);
)
Diese Syntax von übergeben.
und Versand
Anrufe scheinen selbsterklärend zu sein, aber Sie können mehr über diese Tricks lesen hier.
Wenn Sie alle Fehler an einem Ort haben, können Sie sie leicht in Ihre Dashboard
Komponente:
berechnet: mapState((
errors: 'common/errors'
)),
watch: (
/* wird nach jeder "common/ERROR"-Mutation aufgerufen, bei der wir nur neue Fehler nacheinander in den Speicher aufnehmen */
errors() (
this.showErrorMessage(this.errors[0]);
)
)
Das vorherige Beispiel mit der gemeinsame Modul zur Fehlerbehandlung ist bereits eine effiziente Lösung, aber man kann noch weiter gehen.
Wie Sie sehen können, beobachten wir Veränderungen auf der allgemein/fehlerhaft
Array im Speicher. In Fällen wie diesen, wenn Sie eine Aktion für eine bestimmte Mutation bestimmen müssen, können Sie Vuex-Plugins oder sogar Komponenten höherer Ordnung (HOC).
Ich werde die Plugins und HOCs im nächsten Artikel besprechen. In der Zwischenzeit danke ich Ihnen für die Lektüre dieses Eintrags und hoffe, dass Ihnen die Beispiele gefallen haben, die wir vorbereitet haben.
Bleiben Sie dran und programmieren Sie weiter!
Lesen Sie mehr:
– Wie kann man Vue.js-Anwendungen verbessern? Einige praktische Tipps
– GraphQL: Erfahrungen aus der Produktion
– Shopify, Spree oder Solidus? Prüfen Sie, warum Ruby on Rails Ihnen bei der Entwicklung Ihres E-Commerce helfen kann