Vue.js
Vuex
Suche…
Einführung
Vuex ist eine Zustandsverwaltungsstruktur + Bibliothek für Vue.js-Anwendungen. Es dient als zentraler Speicher für alle Komponenten in einer Anwendung. Regeln sorgen dafür, dass der Zustand nur in vorhersehbarer Weise mutiert werden kann. Es ist auch in die Erweiterung der offiziellen Entwicklertools von Vue integriert und bietet erweiterte Funktionen wie Null-Konfigurations-Debugging für Zeitreisen und Export / Import von Status-Snapshots.
Was ist Vuex?
Vuex ist ein offizielles Plugin für Vue.js, das einen zentralisierten Datastore zur Verwendung in Ihrer Anwendung bietet. Sie wird stark von der Flux-Anwendungsarchitektur beeinflusst, die einen unidirektionalen Datenfluss bietet, was zu einem einfacheren Anwendungsdesign und Argumentation führt.
In einer Vuex-Anwendung enthält der Datastore den gesamten Status der gemeinsam genutzten Anwendung . Dieser Zustand wird durch Mutationen geändert, die als Reaktion auf eine Aktion ausgeführt werden, die ein Mutationsereignis über den Dispatcher aufruft.
Ein Beispiel für den Datenfluss in einer Vuex-Anwendung ist in der folgenden Abbildung dargestellt. Diagramm, das unter der MIT- Lizenz verwendet wird, ursprünglich aus dem offiziellen Vuex GitHub-Repo .
Einzelne Vue.js-Anwendungskomponenten können auf das Speicherobjekt zugreifen, um Daten über Getter abzurufen, bei denen es sich um reine Funktionen handelt, die eine Nur-Lese-Kopie der gewünschten Daten zurückgeben.
Die Komponenten können Aktionen haben , die Funktionen sind , die Änderungen an der Komponente eigene Kopie der Daten durchführen, den Dispatcher verwenden , um ein Mutationsereignis zu versenden. Dieses Ereignis wird dann vom Datastore verarbeitet, der den Status bei Bedarf aktualisiert.
Änderungen werden dann automatisch in der gesamten Anwendung übernommen, da alle Komponenten über ihre Getter reaktiv an das Geschäft gebunden werden.
Ein Beispiel, das die Verwendung von Vuex in einem Vue-Projekt veranschaulicht.
const state = {
lastClickTime: null
}
const mutations = {
updateLastClickTime: (state, payload) => {
state.lastClickTime = payload
}
}
const getters = {
getLastClickTime: state => {
return new Date(state.lastClickTime)
}
}
const actions = {
syncUpdateTime: ({ commit }, payload) => {
commit("updateLastClickTime", payload)
},
asyncUpdateTime: ({ commit }, payload) => {
setTimeout(() => {
commit("updateLastClickTime", payload)
}, Math.random() * 5000)
}
}
const store = new Vuex.Store({
state,
getters,
mutations,
actions
})
const { mapActions, mapGetters } = Vuex;
// Vue
const vm = new Vue({
el: '#container',
store,
computed: {
...mapGetters([
'getLastClickTime'
])
},
methods: {
...mapActions([
'syncUpdateTime',
'asyncUpdateTime'
]),
updateTimeSyncTest () {
this.syncUpdateTime(Date.now())
},
updateTimeAsyncTest () {
this.asyncUpdateTime(Date.now())
}
}
})
Und die HTML-Vorlage für das gleiche:
<div id="container">
<p>{{ getLastClickTime || "No time selected yet" }}</p>
<button @click="updateTimeSyncTest">Sync Action test</button>
<button @click="updateTimeAsyncTest">Async Action test</button>
</div>
Hier enthält der Zustand die lastClickTime- Eigenschaft, die als null initialisiert wurde. Diese Einrichtung von Standardwerten ist wichtig , die Eigenschaften reaktiv zu halten. Eigenschaften, die im Zustand nicht erwähnt werden, sind verfügbar, aber die danach vorgenommenen Änderungen sind nicht mit Hilfe von Gettern zugänglich .
Der verwendete Getter stellt eine berechnete Eigenschaft bereit, die jedes Mal aktualisiert wird, wenn eine Mutation den Wert der Eigenschaft state aktualisiert.
Nur Mutationen dürfen den Zustand und seine Eigenschaften ändern, das heißt, dies geschieht nur synchron .
Eine Aktion kann für asynchrone Aktualisierungen verwendet werden, bei denen der API-Aufruf (der hier durch den zufallsgesteuerten setTimeout verspottet wird) in der Aktion ausgeführt werden kann, und nachdem die Antwort abgerufen wurde, eine Mutation ausgeführt werden kann, um die Änderung des Status vorzunehmen .
Warum Vuex verwenden?
Wenn Sie große Anwendungen wie Single-Page-Apps (SPAs) erstellen, die in der Regel aus vielen wiederverwendbaren Komponenten bestehen, können sie sehr schwer zu erstellen und zu warten sein. Die gemeinsame Nutzung von Daten und Zuständen zwischen diesen Komponenten kann auch schnell brechen und das Debugging und die Wartung schwierig werden.
Durch die Verwendung eines zentralen Anwendungsdatenspeichers kann der gesamte Anwendungsstatus an einer Stelle dargestellt werden, wodurch die Anwendung organisierter wird. Durch die Verwendung eines unidirektionalen Datenflusses, durch Mutationen und durch das Festlegen des Zugriffs auf Komponentendaten auf die erforderlichen Daten wird es viel einfacher, die Komponentenrolle und die Auswirkungen auf den Anwendungsstatus zu beurteilen.
VueJS-Komponenten sind separate Entitäten und können Daten nicht einfach untereinander austauschen. Um Daten ohne Vuex gemeinsam zu nutzen, müssen wir ein Ereignis mit Daten emit
und dann das Ereignis mit on
überwachen.
Komponente 1
this.$emit('eventWithDataObject', dataObject)
Komponente 2
this.$on('eventWithDataObject', function (dataObject) {
console.log(dataObject)
})
Wenn vuex installiert ist, können wir einfach von jeder Komponente aus auf die Daten zugreifen, ohne dass Ereignisse abgehört werden müssen.
this.$store.state.myData
Wir können Daten auch synchron mit Mutatoren ändern , asynchrone Aktionen verwenden und Daten mit Getter- Funktionen abrufen .
Getterfunktionen funktionieren möglicherweise als global berechnete Funktionen. Wir können auf sie von Komponenten zugreifen:
this.$store.getters.myGetter
Aktionen sind globale Methoden. Wir können sie aus Komponenten versenden:
this.$store.dispatch('myAction', myDataObject)
Mutationen sind die einzige Möglichkeit, Daten in vuex zu ändern. Wir können Änderungen festschreiben:
this.$store.commit('myMutation', myDataObject)
Vuex-Code würde so aussehen
state: {
myData: {
key: 'val'
}
},
getters: {
myGetter: state => {
return state.myData.key.length
}
},
actions: {
myAction ({ commit }, myDataObject) {
setTimeout(() => {
commit('myMutation', myDataObject)
}, 2000)
}
},
mutations: {
myMutation (state, myDataObject) {
state.myData = myDataObject
}
}
Wie installiere ich Vuex?
In den meisten Fällen verwenden Sie Vuex in größeren komponentenbasierten Anwendungen, in denen Sie wahrscheinlich einen Modul-Bundler wie Webpack oder Browserify in Verbindung mit Vueify verwenden, wenn Sie einzelne Dateien verwenden.
In diesem Fall ist der einfachste Weg, um Vuex zu erhalten, über NPM. Führen Sie den folgenden Befehl aus, um Vuex zu installieren, und speichern Sie es in Ihren Anwendungsabhängigkeiten.
npm install --save vuex
Stellen Sie sicher, dass Sie Vuex mit Ihrem Vue-Setup verknüpfen, indem Sie die folgende Zeile nach der Anweisung von Request require('vue')
einfügen.
Vue.use(require('vuex'))
Vuex ist auch als CDN erhältlich. Sie können die neueste Version von cdnjs hier herunterladen.
Automatisch unzulässige Benachrichtigungen
In diesem Beispiel wird ein Vuex-Modul dynamisch registriert, um benutzerdefinierte Benachrichtigungen zu speichern, die automatisch verworfen werden können
notifications.js
vuex store auflösen und einige Konstanten definieren
//Vuex store previously configured on other side
import _store from 'path/to/store';
//Notification default duration in milliseconds
const defaultDuration = 8000;
//Valid mutation names
const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED';
const NOTIFICATION_DISMISSED = 'NOTIFICATION_DISMISSED';
Setzen Sie unser Modul in den Ausgangszustand
const state = {
Notifications: []
}
Setze unsere Modul-Getter
const getters = {
//All notifications, we are returning only the raw notification objects
Notifications: state => state.Notifications.map(n => n.Raw)
}
Setzen Sie unser Modul Aktionen
const actions = {
//On actions we receive a context object which exposes the
//same set of methods/properties on the store instance
//{commit} is a shorthand for context.commit, this is an
//ES2015 feature called argument destructuring
Add({ commit }, notification) {
//Get notification duration or use default duration
let duration = notification.duration || defaultDuration
//Create a timeout to dismiss notification
var timeOut = setTimeout(function () {
//On timeout mutate state to dismiss notification
commit(NOTIFICATION_DISMISSED, notification);
}, duration);
//Mutate state to add new notification, we create a new object
//for save original raw notification object and timeout reference
commit(NOTIFICATION_ADDED, {
Raw: notification,
TimeOut: timeOut
})
},
//Here we are using context object directly
Dismiss(context, notification) {
//Just pass payload
context.commit(NOTIFICATION_DISMISSED, notification);
}
}
Setze unsere Modulmutationen
const mutations = {
//On mutations we receive current state and a payload
[NOTIFICATION_ADDED](state, notification) {
state.Notifications.push(notification);
},
//remember, current state and payload
[NOTIFICATION_DISMISSED](state, rawNotification) {
var i = state.Notifications.map(n => n.Raw).indexOf(rawNotification);
if (i == -1) {
return;
}
clearTimeout(state.Notifications[i].TimeOut);
state.Notifications.splice(i, 1);
}
}
Registrieren Sie unser Modul mit definiertem Zustand, Eingaben, Aktionen und Mutationen
_store.registerModule('notifications', {
state,
getters,
actions,
mutations
});
Verwendungszweck
componentA.vue
Diese Komponente zeigt alle Benachrichtigungen als Warnmeldungen des Bootstraps in der oberen rechten Ecke des Bildschirms an. Außerdem können Sie jede Benachrichtigung manuell abbrechen.
<template>
<transition-group name="notification-list" tag="div" class="top-right">
<div v-for="alert in alerts" v-bind:key="alert" class="notification alert alert-dismissible" v-bind:class="'alert-'+alert.type">
<button v-on:click="dismiss(alert)" type="button" class="close" aria-label="Close"><span aria-hidden="true">×</span></button>
<div>
<div>
<strong>{{alert.title}}</strong>
</div>
<div>
{{alert.text}}
</div>
</div>
</div>
</transition-group>
</template>
<script>
export default {
name: 'arc-notifications',
computed: {
alerts() {
//Get all notifications from store
return this.$store.getters.Notifications;
}
},
methods: {
//Manually dismiss a notification
dismiss(alert) {
this.$store.dispatch('Dismiss', alert);
}
}
}
</script>
<style lang="scss" scoped>
$margin: 15px;
.top-right {
top: $margin;
right: $margin;
left: auto;
width: 300px;
//height: 600px;
position: absolute;
opacity: 0.95;
z-index: 100;
display: flex;
flex-wrap: wrap;
//background-color: red;
}
.notification {
transition: all 0.8s;
display: flex;
width: 100%;
position: relative;
margin-bottom: 10px;
.close {
position: absolute;
right: 10px;
top: 5px;
}
> div {
position: relative;
display: inline;
}
}
.notification:last-child {
margin-bottom: 0;
}
.notification-list-enter,
.notification-list-leave-active {
opacity: 0;
transform: translateX(-90px);
}
.notification-list-leave-active {
position: absolute;
}
</style>
Snippet zum Hinzufügen einer Benachrichtigung in einer anderen Komponente
//payload could be anything, this example content matches with componentA.vue
this.$store.dispatch('Add', {
title = 'Hello',
text = 'World',
type = 'info',
duration = 15000
});