Principes fondamentaux de Vuex

Vuex est une bibliothèque de gestion d’état centralisée conçue pour les applications Vue.js. Son élément central est le store, qui contient la majorité de l’état de l’application. Il offre une approche réactive : lorsqu’un composant lit des données depuis le store, toute modification ultérieure de ces données entraîne automatiquement une mise à jour du composant.

Une règle importante : l’état du store ne doit jamais être modifié directement. La seule façon de le faire est d’exécuter une mutation via commit. Cela garantit que chaque changement est traçable.

import { createApp } from 'vue'
import { createStore } from 'vuex'

const boutique = createStore({
  state () {
    return {
      compteur: 0
    }
  },
  mutations: {
    augmenter (state) {
      state.compteur++
    }
  }
})

const app = createApp({ /* composant racine */ })
app.use(boutique)

Pour accéder à l’état et déclencher une mutation :

boutique.commit('augmenter')
console.log(boutique.state.compteur) // 1

Dans un composant, on peut utiliser this.$store (avec l’API Options) ou le hook useStore() (avec la Composition API).

// Depuis un composant (Options API)
export default {
  methods: {
    incrementer() {
      this.$store.commit('augmenter')
      console.log(this.$store.state.compteur)
    }
  }
}

Concepts fondamentaux

State

L’état est généralement exposé via des propriétés calculées pour profiter de la réactivité.

const CompteurAffichage = {
  template: `<div>{{ total }}</div>`,
  computed: {
    total () {
      return this.$store.state.compteur
    }
  }
}

L’assistant mapState simplifie le mappage de plusiuers états dans les propriétés calculées.

import { mapState } from 'vuex'

export default {
  computed: mapState({
    total: state => state.compteur,
    // alias
    valeur: 'compteur',
    // utiliser l’état local (this)
    totalPlusLocal (state) {
      return state.compteur + this.ajoutLocal
    }
  })
}

On peut fusionner avec d’autres propriétés calculées grâce à l’opérateur de décomposition :

computed: {
  autreCalcul() { /* ... */ },
  ...mapState({
    total: state => state.compteur
  })
}

Getters

Les getters permettent de dériver ou de filtrer l’état avant de le fournir aux composants.

const boutique = createStore({
  state: {
    tâches: [
      { id: 1, texte: 'Apprendre Vuex', fini: true },
      { id: 2, texte: 'Construire une app', fini: false }
    ]
  },
  getters: {
    tâchesFinies (state) {
      return state.tâches.filter(t => t.fini)
    }
  }
})

Pour obtenir la liste, on utilise boutique.getters.tâchesFinies. Un getter peut recevoir d’autres getters comme second paramètre.

Pour passer des paramètres à un getter, on renvoie une fonction :

getters: {
  tâcheParId: (state) => (id) => {
    return state.tâches.find(t => t.id === id)
  }
}
// usage : boutique.getters.tâcheParId(2)

L’auxiliaire mapGetters projette les getters dans les propriétés calculées locales.

import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters([
      'tâchesFinies',
      'autreGetter'
    ])
  }
}

Pour renommer, on utilise un objet :

...mapGetters({
  finies: 'tâchesFinies'
})

Mutation

Les mutations sont les seules responsables de la modification de l’état. Elles doivent être synchrones pour garantir la prévisibilité et le suivi.

Action

Les actions sont similaires aux mutations, mais au lieu de modifier directement l’état, elles committent des mutations. Elles peuvent contenir des opérations asynchrones (appels API, timers, etc.). On les déclenche via store.dispatch.

actions: {
  incrémenterAsync ({ commit }) {
    setTimeout(() => {
      commit('augmenter')
    }, 1000)
  }
}
// dans un composant : boutique.dispatch('incrémenterAsync')

Modules

Lorsque l’application grandit, le store peut être divisé en modules. Chaque module possède son propre état, mutations, actions et getters. Cela permet une meilleure organisation du code.

const moduleA = {
  state: () => ({ compteur: 10 }),
  mutations: { augmenter (state) { state.compteur++ } },
  actions: { /* ... */ },
  getters: { double (state) { return state.compteur * 2 } }
}

const boutique = createStore({
  modules: {
    a: moduleA
  }
})

console.log(boutique.state.a.compteur) // 10

Étiquettes: Vuex gestion-etat Store mutations getters

Publié le 9 octobre à 09h17