Sök…


Introduktion

Vuex är ett tillståndshanteringsmönster + bibliotek för Vue.js-applikationer. Det fungerar som en centraliserad butik för alla komponenter i en applikation, med regler som säkerställer att staten endast kan muteras på ett förutsägbart sätt. Den integreras också med Vues officiella förlängning av dev-verktyg för att tillhandahålla avancerade funktioner såsom nollkonfigurering av tidfärdsfelsökning och status / export / import av stillbild.

Vad är Vuex?

Vuex är ett officiellt plugin för Vue.js som erbjuder en centraliserad datastore för användning i din applikation. Det påverkas starkt av Flux-applikationsarkitekturen, som har ett riktningslöst dataflöde som leder till enklare applikationsdesign och resonemang.

Inom en Vuex-applikation har datastore alla delade applikationstillstånd . Detta tillstånd förändras av mutationer som utförs som svar på en åtgärd som åberopar en mutationshändelse via avsändaren .

Ett exempel på dataflödet i en Vuex-applikation visas i diagrammet nedan. Vuex applikationsarkitektur Diagram som används under MIT- licensen, ursprungligen från den officiella Vuex GitHub-repo .

Enskilda Vue.js-applikationskomponenter kan få åtkomst till butikobjektet för att hämta data via getters , som är rena funktioner som returnerar en skrivskyddad kopia av önskad data.

Komponenter kan ha handlingar som är funktioner som utför ändringar i komponentens egna kopia av data och sedan använda avsändaren för att skicka en mutationshändelse. Denna händelse hanteras sedan av datalagret som uppdaterar tillståndet vid behov.

Ändringar återspeglas sedan automatiskt i hela applikationen eftersom alla komponenter är reaktivt bundna till butiken via deras getters.


Ett exempel som illustrerar användningen av vuex i ett Vue-projekt.

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())
    }
  }
})

Och HTML-mallen för samma:

<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>
  1. Här innehåller staten lastClickTime- egenskapen initialiserad som null. Denna inställning av standardvärden är viktig för att hålla egenskaperna reaktiva . Egenskaper som inte nämns i staten kommer att finnas tillgängliga men ändringarna som gjorts därefter skulle inte vara tillgängliga genom att använda getters.

  2. Den getter som används, ger en beräknad egenskap som kommer att uppdateras varje gång en mutation uppdaterar värdet på den statliga egenskapen.

  3. Endast mutationer får ändra tillståndet och dess egenskaper, det sagt, det gör det bara synkront .

  4. En åtgärd kan användas i fallet med asynkrona uppdateringar, där API-samtalet (här hånat av den slumpmässigt tidsinställda setTimeout) kan göras i åtgärden, och efter att ha fått svaret kan en mutation åta sig att göra ändringen till staten .

Varför använda Vuex?

När man bygger stora applikationer som SPA: er, som vanligtvis består av många återanvändbara komponenter, kan de snabbt bli svåra att bygga och underhålla. Delning av data och tillstånd mellan dessa komponenter kan också snabbt bryta ner och bli svårt att felsöka och underhålla.

Genom att använda en centraliserad applikationsdatalager kan hela applikationstillståndet representeras på ett ställe vilket gör applikationen mer organiserad. Genom att använda ett enkelriktat dataflöde, mutationer och genom att utvidga komponentdata åtkomst till endast de data som krävs blir det mycket enklare att resonera om komponentrollen och hur den ska påverka applikationstillståndet.

VueJS-komponenter är separata enheter och de kan inte enkelt dela data mellan varandra. För att dela data utan vuex måste vi emit händelse med data och sedan lyssna och fånga händelsen med on .

komponent 1

this.$emit('eventWithDataObject', dataObject)

komponent 2

this.$on('eventWithDataObject', function (dataObject) {
    console.log(dataObject)
})

Med vuex installerat kan vi helt enkelt komma åt dess data från valfri komponent utan att behöva lyssna på händelser.

this.$store.state.myData

Vi kan också ändra data synkront med mutatorer , använda asynkrona åtgärder och få data med getterfunktioner .

Getterfunktioner kan fungera som globala beräknade funktioner. Vi kan komma åt dem från komponenter:

this.$store.getters.myGetter

Åtgärder är globala metoder. Vi kan skicka dem från komponenter:

this.$store.dispatch('myAction', myDataObject)

Och mutationer är det enda sättet att ändra data i vuex. Vi kan göra ändringar:

this.$store.commit('myMutation', myDataObject)

Vuex-kod skulle se ut så här

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
  }
}

Hur installerar jag Vuex?

För det mesta kommer du att använda Vuex i större komponentbaserade applikationer där du troligtvis använder en modulbuntare som Webpack eller Browserify tillsammans med Vueify om du använder enstaka filer.

I detta fall är det enklaste sättet att få Vuex från NPM. Kör kommandot nedan för att installera Vuex och spara det i dina applikationsberoenden.

 npm install --save vuex

Se till att du laddar länk Vuex med din Vue-inställning genom att placera följande rad efter ditt require('vue') .

Vue.use(require('vuex'))

Vuex är också tillgängligt på CDN; du kan ta tag i den senaste versionen från cdnjs här .

Auto avvisbara aviseringar

Det här exemplet registrerar en vuexmodul dynamiskt för att lagra anpassade aviseringar som automatiskt kan tas bort

notifications.js

lösa vuex-lagring och definiera vissa konstanter

//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';

ställa in vårt modul initialtillstånd

const state = {
  Notifications: []
}

ställa in våra modulgetters

const getters = {
  //All notifications, we are returning only the raw notification objects
  Notifications: state => state.Notifications.map(n => n.Raw)
}

ställa in våra modulåtgärder

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);
  }
}

ställa in våra modulmutationer

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);
  }
}

Registrera vår modul med definierat tillstånd, bokstäver, åtgärder och mutation

_store.registerModule('notifications', {
  state,
  getters,
  actions,
  mutations
});

Användande

componentA.vue

Denna komponent visar alla aviseringar som bootstraps varningar i övre högra hörnet av skärmen, gör det också möjligt att manuellt avvisa varje avisering.

<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">&times;</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>

Utdrag för att lägga till meddelande i någon annan komponent

//payload could be anything, this example content matches with componentA.vue 
this.$store.dispatch('Add', {
  title = 'Hello',
  text = 'World',
  type = 'info',
  duration = 15000
});


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow