Fermer

octobre 14, 2024

Bases de Vue : gestion de l’état de Pinia

Bases de Vue : gestion de l’état de Pinia


Pour une gestion simple de l’état dans Vue, regardons Pinia, qui nous permet de stocker et de partager des données entre les composants et la page.

Il viendra un moment dans la plupart des applications où vous aurez deux éléments de votre application que vous souhaitiez partager un état réactif commun. Un bon exemple de ceci est le partage des informations utilisateur entre un composant d’en-tête et un formulaire de modification utilisateur profondément imbriqué dans votre application.

Le problème

Considérez l’arborescence des composants suivante pour une application.

L'application pointe vers l'en-tête et les paramètres. Paramètres pointe vers les paramètres utilisateur, pointe vers le formulaire utilisateur

Dis maintenant que tu as besoin d’un user objet que vous avez récupéré de l’API sur le App composant avec à la fois le Header et le UserForm. Vous pourriez certainement commencer à créer un accessoire et émettre des serpents et des échelles le long des deux arbres, mais dans une application plus complexe où UserForm ou tout autre composant nécessitant un accès à un état réactif partagé, cela peut rapidement devenir incontrôlable.

La ou les solutions

Vue 3 est livré avec quelques outils pour gérer un tel problème. La première approche serait de transmettre le user objet selon les besoins jusqu’aux accessoires comme nous l’avons mentionné précédemment. Cela peut rapidement devenir incontrôlable, car nous pourrions potentiellement être confrontés à un N quantité de composants à travers lesquels poser l’accessoire, et si nous devons plus tard ajouter plus de propriétés à injecter dans l’arbre, cela peut vraiment s’additionner.

Une deuxième approche consisterait à exploiter provide et inject. Cela dépasse le cadre de cet article, mais je peux déjà vous le gâcher et dire que, tant que c’est le cas, un solution, ce n’est pas la meilleur solution. Provide et inject sont des outils extrêmement puissants et flexibles, et comme tout outil combinant ces attributs, ils présentent de nombreux inconvénients, en particulier lorsque vous travaillez avec de grandes équipes ou des bases de code, car ils peuvent très rapidement devenir des spaghettis ingérables.

Une troisième approche lorsqu’il s’agit spécifiquement d’un état provenant exclusivement de votre API consiste à utiliser des bibliothèques de gestion d’état asynchrone telles que Requête Tanstack si vous disposez d’une API RESTful ou Vue d’Apollon si vous utilisez GraphQL. Ce sont des outils extrêmement puissants et vous devriez vous familiariser avec eux (à mon avis), mais ils sont conçus pour être utilisés avec des données réseau et non comme un magasin.

La solution que nous allons explorer aujourd’hui est Ananasun magasin de gestion d’état simple et facile à utiliser pour Vue 3. Ce magasin nous permet de partager des données entre les composants et la page de manière transparente tout en conservant un état centralisé. Jetons un coup d’oeil.

Configuration de Pinia

La configuration de Pinia pour un SPA Vue 3 est très simple. Comme d’habitude, si vous créez une nouvelle application à partir de zéro, le npm ou le fil create Le script Vue vous demandera si vous souhaitez utiliser Pinia comme gestion d’état de votre choix.

Pour l’incorporer manuellement dans votre application ou pour l’ajouter à une application existante, nous devons suivre quelques étapes.

Tout d’abord, ajoutez le package à votre application avec soit npm ou yarn.

yarn add pinia
# or
npm install pinia

Nous devons ensuite accéder à notre application main.js ou index.js (ou partout où vous montez votre application) fichier et utilisez Vue.use pour l’ajouter à notre application.

main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

C’est ça! Nous pouvons maintenant passer à la création de notre propre boutique utilisateur.

Notre premier magasin Pinia

Nous allons créer un magasin d’utilisateurs pour continuer avec notre exemple d’application inventé à partir de l’arborescence ci-dessus. Pour ajouter une boutique, nous devons créer un nouveau fichier qui contiendra le code de celui-ci, je vous recommande d’ajouter ces fichiers sous un stores dossier à garder en ordre.

UserStore.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {

})

Pour créer une boutique, nous utilisons le defineStore méthode exposée par pinia. Il faut deux paramètres principaux. Le premier sera le id du magasin ; cela peut être tout ce que vous préférez, mais il doit être unique à votre application : « utilisateur » est le plus logique pour notre exemple puisque c’est ce que le magasin contiendra.

Le deuxième paramètre est un objet qui contient les options du magasin, regardons ce que nous pouvons ajouter ici.

État

La première propriété que nous ajouterons aux options est la statesi vous êtes familier avec l’API d’options de Vue, cela vous conviendra parfaitement, car state pour un magasin, c’est fondamentalement la même chose. C’est une fonction qui renvoie un objet qui contiendra tout l’état que nous voulons que ce magasin garde pour nous. Par souci d’exemple, nous ajouterons un user propriété et un isLoading drapeau.

UserStore.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => {
    return {
      isLoading: false,
      user: null
    }
  }
})

Aussi vite que cela nous pouvons déjà importer cette boutique dans notre maquette UserForm.vue composant et utiliser le isLoading et user États.

UserForm.vue

<template>
  <p v-if="store.isLoading">Loading!</p>
  <form> 
    <input :value="store.user.name" />
  </form>
</template>

<script setup>
import { useUserStore } from './stores/UserStore.js'
const store = useUserStore()
</script>

Dans l’exemple ci-dessus, nous importons le useUserStore puis appeler la méthode. Cela nous renvoie une copie du magasin d’utilisateurs que nous venons de créer. L’état de ce magasin est partagé, donc toutes les modifications que nous y apporterons seront bien sûr partagées par tous les autres composants utilisant le magasin.

Remarquez dans le modèle que nous pouvons maintenant utiliser le isLoading drapeau pour vérifier l’état et afficher un message convivial, et lier le user.name propriété à une entrée pour une utilisation ultérieure.

Getteurs

Semblable à computed valeurs, nous pouvons créer des getters à l’intérieur de notre magasin. Un exemple simple serait un getter qui joint le nom et le nom de famille de l’utilisateur. Essayons celui-là.

UserStore.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => {
    return {
      isLoading: false,
      user: null
    }
  },
  getters: {
    userFullName: (state) => state.user.name + ' ' + state.user.lastName
  }
})

Aussi simple que ce serait de créer un computed propriété, nous avons maintenant un userFullName getter que nous pouvons utiliser dans nos composants. Passons à la simulation Header.vue composant et utilisez-le pour afficher un message pour nos utilisateurs.

Notez que le getter reçoit un paramètre state avec l’état actuel du magasin. Il contiendra toutes les propriétés de state nous avons créé au préalable ainsi que tous les autres getters. De plus, il est important de garder à l’esprit que getters peut pas soyez asynchrone !

Header.vue

<template>
<header>
  Welcome {{ store.userFullName }}
</header>
</template>

<script setup>
import { useUserStore } from './stores/UserStore.js'
const store = useUserStore()
</script>

Notez qu’une fois de plus, nous importons le magasin et appelons le useUserStore méthode pour le créer. Ce magasin pointe vers le même état que celui que nous avons créé précédemment sur le UserForm.vue fichier, donc si l’utilisateur change de nom, cela sera également reflété ici.

Le getter que nous avons créé, userFullNamepeut être utilisé directement depuis le magasin, comme indiqué dans l’exemple ci-dessus.

Actes

La dernière option que nous pouvons ajouter à notre magasin est actionsce sont l’équivalent de celui d’un composant methods. Contrairement à getters, methods peut être asynchrone et contenir des appels API. C’est un bon emplacement pour configurer notre logique afin de charger les données de l’utilisateur.

UserStore.js

import { defineStore } from 'pinia'
import { getCurrentUser } from './api/user'

export const useUserStore = defineStore('user', {
  state: () => {
    return {
      isLoading: false,
      user: null
    }
  },
  getters: {
    userFullName: (state) => state.user.name + ' ' + state.user.lastName
  },
  methods: {
    async loadUser () {
      this.isLoading = true
      
      const data = await getCurrentUser()
      this.user = data      

      this.isLoading = false
    }
  }
})

Nous avons importé une simulation getCurrentUser Appel API en haut du fichier, cela créerait très probablement un GET appel à un point de terminaison pour récupérer l’utilisateur.

Ensuite, nous avons créé une nouvelle méthode sur notre boutique loadUser. Cette méthode définit le isLoading drapeau à true afin que l’utilisateur sache que quelque chose se passe, puis effectue un appel asynchrone au getUser méthode. Lorsque nous recevons les données, nous les stockons dans notre user état, puis réinitialisez le isLoading drapeau à false.

Quelques éléments manquants dans cet exemple sont la gestion des erreurs et la double vérification pour voir si nous avons déjà un utilisateur dans l’état avant de faire une nouvelle requête réseau pour le récupérer, mais cela sort du cadre de cet article.

Maintenant, nous pouvons retourner à notre UserForm.vue composant et appelez cette méthode.

<template>
  <p v-if="store.isLoading">Loading!</p>
  <form> 
    <input :value="store.user.name" />
  </form>
</template>

<script setup>
import { useUserStore } from './stores/UserStore.js'
const store = useUserStore()

store.loadUser()
</script>

Désormais, lorsque notre composant se chargera, il appellera le loadUser méthode de notre magasin et chargez l’utilisateur à partir de l’API. Dès que l’utilisateur est chargé, le Header.vue Le composant affichera le userFullName getter que nous avons créé. Rappelez-vous, le user l’état est commun entre tous les composants qui utilisent ce magasin.

Conclusion

Cela ne fait qu’effleurer la surface de ce que vous pouvez faire avec Pinia. Comme pour toute bibliothèque, je vous recommande de vous plonger profondément dans leur documentation car il est très bien écrit et vous aidera à apprendre non seulement les principes fondamentaux mais également les parties les plus complexes de cette étonnante bibliothèque.

Néanmoins, vous maîtrisez désormais les bases et pouvez commencer à créer vos propres magasins Pinia !




Source link