Vue.js
Vuex
Zoeken…
Invoering
Vuex is een statusbeheerpatroon + bibliotheek voor Vue.js-applicaties. Het dient als een gecentraliseerde winkel voor alle componenten in een applicatie, met regels die ervoor zorgen dat de staat alleen op een voorspelbare manier kan worden gemuteerd. Het integreert ook met de officiële uitbreiding van Vue tools om geavanceerde functies te bieden, zoals zero-config time-travel debugging en export / import van momentopnames.
Wat is Vuex?
Vuex is een officiële plug-in voor Vue.js die een gecentraliseerde datastore biedt voor gebruik binnen uw applicatie. Het wordt sterk beïnvloed door de Flux-applicatiearchitectuur met een unidirectionele gegevensstroom die leidt tot eenvoudiger applicatieontwerp en redenering.
Binnen een Vuex-applicatie heeft de datastore de status van alle gedeelde applicaties . Deze status wordt gewijzigd door mutaties die worden uitgevoerd als reactie op een actie die een mutatiegebeurtenis oproept via de verzender .
Een voorbeeld van de gegevensstroom in een Vuex-toepassing is in het onderstaande diagram weergegeven. Diagram gebruikt onder de MIT- licentie, oorspronkelijk van de officiële Vuex GitHub-repo .
Individuele Vue.js-applicatiecomponenten hebben toegang tot het winkelobject om gegevens op te halen via getters , die pure functies zijn die een alleen-lezen kopie van de gewenste gegevens retourneren.
Componenten kunnen acties hebben die functies zijn die wijzigingen aanbrengen in de eigen kopie van de gegevens van de component, en vervolgens de coördinator gebruiken om een mutatiegebeurtenis te verzenden. Deze gebeurtenis wordt vervolgens afgehandeld door de gegevensopslag die de status indien nodig bijwerkt.
Wijzigingen worden vervolgens automatisch doorgevoerd in de toepassing, omdat alle componenten via hun getters reactief aan de winkel zijn gebonden.
Een voorbeeld van het gebruik van vuex in een vue-project.
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())
}
}
})
En de HTML-sjabloon voor hetzelfde:
<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 de staat bevat lastClickTime eigendom geïnitialiseerd als nul. Dit instellen van standaardwaarden is belangrijk om de eigenschappen reactief te houden. Eigenschappen die niet in de status worden vermeld , zijn beschikbaar, maar de wijzigingen die daarna worden aangebracht, zijn niet toegankelijk met getters.
De gebruikte getter biedt een berekende eigenschap die wordt bijgewerkt telkens wanneer een mutatie de waarde van de eigenschap state bijwerkt.
Alleen mutaties mogen de status en de eigenschappen ervan wijzigen, maar dit gebeurt alleen synchroon .
Een actie kan worden gebruikt in het geval van asynchrone updates, waarbij de API-aanroep (hier bespot door de willekeurig getimede setTimeout) in de actie kan worden gemaakt, en na het ontvangen van de reactie kan een mutatie worden gecommitteerd om de status te wijzigen .
Waarom Vuex gebruiken?
Bij het bouwen van grote applicaties zoals Single Page Apps (SPA's), die meestal uit veel herbruikbare componenten bestaan, kunnen ze snel moeilijk te bouwen en te onderhouden worden. Het delen van gegevens en status tussen deze componenten kan ook snel mislukken en moeilijk te debuggen en te onderhouden worden.
Door een gecentraliseerde applicatiegegevensopslag te gebruiken, kan de volledige applicatiestatus op één plaats worden weergegeven, waardoor de applicatie meer georganiseerd is. Door het gebruik van een unidirectionele datastroom, mutaties en door de toegang tot componentgegevens tot alleen de vereiste gegevens, wordt het veel eenvoudiger om te redeneren over de componentrol en hoe deze de applicatiestatus zou moeten beïnvloeden.
VueJS-componenten zijn afzonderlijke entiteiten en kunnen niet gemakkelijk gegevens met elkaar delen. Om gegevens zonder vuex te delen, moeten we een gebeurtenis met gegevens emit
en vervolgens luisteren en die gebeurtenis vangen met on
.
component 1
this.$emit('eventWithDataObject', dataObject)
component 2
this.$on('eventWithDataObject', function (dataObject) {
console.log(dataObject)
})
Als vuex is geïnstalleerd, hebben we eenvoudig toegang tot de gegevens van elk onderdeel zonder naar gebeurtenissen te hoeven luisteren.
this.$store.state.myData
We kunnen ook gegevens synchroon wijzigen met mutators , asynchrone acties gebruiken en gegevens ophalen met getter- functies.
Getter-functies werken mogelijk als globale berekende functies. We kunnen ze openen vanuit componenten:
this.$store.getters.myGetter
Acties zijn globale methoden. We kunnen ze verzenden vanuit componenten:
this.$store.dispatch('myAction', myDataObject)
En mutaties zijn de enige manier om gegevens in vuex te wijzigen. We kunnen wijzigingen doorvoeren:
this.$store.commit('myMutation', myDataObject)
Vuex-code zou er zo uitzien
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
}
}
Hoe Vuex te installeren?
Meestal zult u Vuex gebruiken in grotere componentgebaseerde applicaties waar u waarschijnlijk een modulebundelaar zoals Webpack of Browserify in combinatie met Vueify gebruikt als u afzonderlijke bestanden gebruikt.
In dit geval is de eenvoudigste manier om Vuex te krijgen van NPM. Voer de onderstaande opdracht uit om Vuex te installeren en op te slaan in de afhankelijkheden van uw toepassing.
npm install --save vuex
Zorg ervoor dat u link Vuex laadt met uw Vue-instelling door de volgende regel te plaatsen na uw require('vue')
instructie.
Vue.use(require('vuex'))
Vuex is ook beschikbaar op CDN; je kunt de nieuwste versie van cdnjs hier downloaden .
Automatisch afwijzende meldingen
In dit voorbeeld wordt een vuex-module dynamisch geregistreerd voor het opslaan van aangepaste meldingen die automatisch kunnen worden afgewezen
notifications.js
vuex store oplossen en enkele constanten definiëren
//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';
stel de initiële status van onze module in
const state = {
Notifications: []
}
stel onze module getters in
const getters = {
//All notifications, we are returning only the raw notification objects
Notifications: state => state.Notifications.map(n => n.Raw)
}
stel onze module Acties in
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);
}
}
stel onze module mutaties in
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);
}
}
Registreer onze module met gedefinieerde status, getters, acties en mutatie
_store.registerModule('notifications', {
state,
getters,
actions,
mutations
});
Gebruik
componentA.vue
Deze component toont alle meldingen als waarschuwingen van de bootstrap in de rechterbovenhoek van het scherm, en maakt het ook mogelijk om elke melding handmatig te negeren.
<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>
Fragment voor het toevoegen van een melding in een ander onderdeel
//payload could be anything, this example content matches with componentA.vue
this.$store.dispatch('Add', {
title = 'Hello',
text = 'World',
type = 'info',
duration = 15000
});