Utiliser Vuex pour la gestion d'états
Partager un état global entre plusieurs composants
1. Problématique
a. Le flux de donnée unidirectionnel
Pour rappel, Vue.js utilise un flux unidirectionnel pour mettre à jour les données du modèle depuis la vue et appliquer ces modifications lors du rendu suivant :
Le processus fonctionne de la manière suivante avec une instance Vue.
-
View : l’utilisateur interagit avec la vue, via le clic d’un bouton, par exemple. Le bouton appelle une action, via une méthode de l’instance Vue.
-
Action : cette action mute l’état de l’application en modifiant les données réactives du modèle.
-
State : l’état de l’application est maintenant différent. Avec son mécanisme de liaison de données (data-binding), Vue.js met à jour en conséquence la vue avec un nouveau rendu.
On peut dire qu’une application Vue.js est pilotée par les données.
Une application Vue.js est un arbre de composants. Chaque composant possède des données réactives qui définissent son état. L’état de chaque composant représente ainsi en définitive l’état de l’application.
On peut rapidement rencontrer différentes problématiques lorsqu’on souhaite partager un état entre plusieurs composants.
-
Problème 1 : partager cette donnée en lecture. Si plusieurs composants souhaitent afficher la même donnée réactive, comment la partager ? La vue d’un composant peut afficher une donnée réactive de son modèle mais ne peut pas accéder aux données réactives d’un autre composant.
-
Problème 2 : partager cette donnée en modification. Plusieurs actions effectuées à partir de différentes vues peuvent être destinées à modifier des données réactives partagées.
Comment résoudre ces deux problèmes ?
b. Utiliser les props et les évènements pour partager et accéder à l’état global
Pour passer des données réactives d’un composant parent à un composant enfant, nous avons vu dans le chapitre Utiliser les composants qu’on utilise les props....
Installer et utiliser le store Vuex
1. Installation
a. Avec un CDN
Pour installer Vuex, si vous n’utilisez pas d’empaqueteur de module, vous pouvez utiliser un CDN en insérant cette ligne dans la page web :
<script src="https://unpkg.com/vuex@3.6.0/dist/vuex.js" />
b. Avec npm ou yarn
Si vous utilisez un empaqueteur de module, vous pouvez installer Vuex avec le gestionnaire de dépendances npm ou yarn.
Dans un terminal, placez-vous à la racine de votre projet et tapez la ligne de commande suivante :
// avec npm
npm install vuex --save
// avec yarn
yarn add vuex
Utilisez ensuite la méthode Vue.use() pour déclarer le module de manière globale dans votre application :
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
Pour créer le store, on utilise la méthode Vuex.Store(), qui prend en paramètre un objet contenant l’état, les accesseurs, les mutateurs, les actions et les modules.
On passe ensuite le store dans les options d’instance lors de l’instanciation de l’instance Vue racine.
// fichier main.js
import Vue from 'vue';
import Vuex from 'vuex';
import App from './App.vue';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
},
});
new Vue({
store,
render: (h) => h(App),
}).$mount('#app');
Le store sera maintenant injecté dans tous les composants enfants de l’instance Vue racine et accessible via la variable d’instance this.$store.
c. Avec Vue CLI
Si vous avez installé votre projet avec Vue CLI mais que Vuex n’est pas encore installé, vous pouvez installer Vuex avec la commande suivante :
vue add vuex
Un fichier store/index.js est créé automatiquement :
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({ ...
Utiliser les modules pour organiser son store
1. Séparer le store en plusieurs fichiers
Pour de larges applications, le fichier store/index.js peut vite devenir volumineux. Si l’on souhaite gagner en lisibilité, il serait intéressant de pouvoir séparer l’état du store en plusieurs fichiers. Chaque fichier contiendrait une partie du store avec les mutations et actions associées.
La première approche qui vient à l’esprit est d’utiliser les modules ES6 :
// fichier store/partA.js
export default {
state: {
count: 0
},
mutations: {
CHANGE_COUNT(state, number) {
state.count = number;
}
}
};
// fichier store/partB.js
export default {
state: {
message: "mon message"
},
mutations: {
CHANGE_MESSAGE(state, message) {
state.message = message;
}
}
};
On fusionne ensuite les différentes parties pour chaque propriété du store en utilisant la décomposition :...