En aquest tema, explorarem com gestionar l'estat de l'aplicació utilitzant Vuex, la biblioteca oficial de gestió d'estat per a Vue.js. Vuex segueix el patró Flux i proporciona un emmagatzematge centralitzat per a totes les dades de l'aplicació, permetent una gestió més eficient i estructurada de l'estat.
Continguts
- Introducció a l'estat de Vuex
- Getters
- Mutacions
- Accions
- Exemple pràctic
- Exercicis
- Introducció a l'estat de Vuex
L'estat de Vuex és un objecte que conté totes les dades de l'aplicació. Aquest estat és reactiu, el que significa que qualsevol canvi en l'estat es reflectirà automàticament en la interfície d'usuari.
Exemple de configuració de l'estat
// store.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { count: 0 } });
En aquest exemple, hem creat un estat amb una propietat count
inicialitzada a 0.
- Getters
Els getters són similars a les propietats computades per a l'estat de Vuex. Permeten accedir a l'estat de manera derivada i poden ser utilitzats per calcular valors basats en l'estat.
Exemple de getters
// store.js export default new Vuex.Store({ state: { count: 0 }, getters: { doubleCount: state => state.count * 2 } });
En aquest exemple, hem creat un getter doubleCount
que retorna el doble del valor de count
.
- Mutacions
Les mutacions són l'única manera de canviar l'estat de Vuex. Les mutacions són síncrones i es defineixen com a funcions que reben l'estat com a primer argument i un payload opcional com a segon argument.
Exemple de mutacions
// store.js export default new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; }, incrementBy(state, payload) { state.count += payload.amount; } } });
En aquest exemple, hem creat dues mutacions: increment
, que incrementa count
en 1, i incrementBy
, que incrementa count
per un valor especificat en el payload.
- Accions
Les accions són similars a les mutacions, però poden ser asíncrones. Les accions es defineixen com a funcions que reben un context com a primer argument, el qual conté l'estat, els getters, les mutacions i altres accions.
Exemple d'accions
// store.js export default new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; } }, actions: { incrementAsync({ commit }) { setTimeout(() => { commit('increment'); }, 1000); } } });
En aquest exemple, hem creat una acció incrementAsync
que incrementa count
després d'un segon.
- Exemple pràctic
Ara que hem vist els conceptes bàsics, anem a crear una aplicació senzilla que utilitzi estat, getters, mutacions i accions.
Configuració de l'estat, getters, mutacions i accions
// store.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { count: 0 }, getters: { doubleCount: state => state.count * 2 }, mutations: { increment(state) { state.count++; }, incrementBy(state, payload) { state.count += payload.amount; } }, actions: { incrementAsync({ commit }) { setTimeout(() => { commit('increment'); }, 1000); }, incrementByAsync({ commit }, payload) { setTimeout(() => { commit('incrementBy', payload); }, 1000); } } });
Utilització de Vuex en un component
<template> <div> <p>Count: {{ count }}</p> <p>Double Count: {{ doubleCount }}</p> <button @click="increment">Increment</button> <button @click="incrementAsync">Increment Async</button> <button @click="incrementByAsync({ amount: 5 })">Increment by 5 Async</button> </div> </template> <script> import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'; export default { computed: { ...mapState(['count']), ...mapGetters(['doubleCount']) }, methods: { ...mapMutations(['increment']), ...mapActions(['incrementAsync', 'incrementByAsync']) } }; </script>
En aquest exemple, hem creat un component que mostra el valor de count
i doubleCount
, i proporciona botons per incrementar count
de manera síncrona i asíncrona.
- Exercicis
Exercici 1
Crea una aplicació Vuex que gestioni una llista de tasques. L'estat ha de contenir una llista de tasques, i has de proporcionar getters, mutacions i accions per afegir, eliminar i marcar tasques com a completades.
Solució
// store.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ state: { tasks: [] }, getters: { completedTasks: state => state.tasks.filter(task => task.completed), pendingTasks: state => state.tasks.filter(task => !task.completed) }, mutations: { addTask(state, task) { state.tasks.push(task); }, removeTask(state, taskId) { state.tasks = state.tasks.filter(task => task.id !== taskId); }, toggleTaskCompletion(state, taskId) { const task = state.tasks.find(task => task.id === taskId); if (task) { task.completed = !task.completed; } } }, actions: { addTaskAsync({ commit }, task) { setTimeout(() => { commit('addTask', task); }, 1000); }, removeTaskAsync({ commit }, taskId) { setTimeout(() => { commit('removeTask', taskId); }, 1000); }, toggleTaskCompletionAsync({ commit }, taskId) { setTimeout(() => { commit('toggleTaskCompletion', taskId); }, 1000); } } });
Exercici 2
Modifica l'aplicació de l'exercici anterior per utilitzar mòduls de Vuex per organitzar millor el codi.
Solució
// store/modules/tasks.js const state = { tasks: [] }; const getters = { completedTasks: state => state.tasks.filter(task => task.completed), pendingTasks: state => state.tasks.filter(task => !task.completed) }; const mutations = { addTask(state, task) { state.tasks.push(task); }, removeTask(state, taskId) { state.tasks = state.tasks.filter(task => task.id !== taskId); }, toggleTaskCompletion(state, taskId) { const task = state.tasks.find(task => task.id === taskId); if (task) { task.completed = !task.completed; } } }; const actions = { addTaskAsync({ commit }, task) { setTimeout(() => { commit('addTask', task); }, 1000); }, removeTaskAsync({ commit }, taskId) { setTimeout(() => { commit('removeTask', taskId); }, 1000); }, toggleTaskCompletionAsync({ commit }, taskId) { setTimeout(() => { commit('toggleTaskCompletion', taskId); }, 1000); } }; export default { state, getters, mutations, actions };
// store/index.js import Vue from 'vue'; import Vuex from 'vuex'; import tasks from './modules/tasks'; Vue.use(Vuex); export default new Vuex.Store({ modules: { tasks } });
Conclusió
En aquest tema, hem après com gestionar l'estat de l'aplicació utilitzant Vuex. Hem vist com definir l'estat, getters, mutacions i accions, i hem creat una aplicació pràctica per posar en pràctica aquests conceptes. A més, hem proporcionat exercicis per reforçar els coneixements adquirits. En el proper tema, explorarem com utilitzar mòduls a Vuex per organitzar millor el codi de l'aplicació.
Curs de Vue.js
Mòdul 1: Introducció a Vue.js
- Què és Vue.js?
- Configuració de l'entorn de desenvolupament
- Creant la teva primera aplicació Vue
- Entenent la instància de Vue
Mòdul 2: Conceptes bàsics de Vue.js
- Sintaxi de plantilles
- Enllaç de dades
- Propietats computades i observadors
- Enllaços de classes i estils
- Renderització condicional
- Renderització de llistes
Mòdul 3: Components de Vue.js
- Introducció als components
- Props i esdeveniments personalitzats
- Slots
- Components dinàmics i asíncrons
- Comunicació entre components
Mòdul 4: Vue Router
- Introducció a Vue Router
- Configuració de Vue Router
- Rutes dinàmiques
- Rutes niades
- Guàrdies de navegació
Mòdul 5: Gestió d'estat amb Vuex
- Introducció a Vuex
- Estat, getters, mutacions i accions
- Mòduls a Vuex
- Utilitzant Vuex en components
- Patrons avançats de Vuex
Mòdul 6: Directives de Vue.js
Mòdul 7: Plugins de Vue.js
Mòdul 8: Proves en Vue.js
Mòdul 9: Conceptes avançats de Vue.js
- Funcions de renderització i JSX
- Renderització del costat del servidor (SSR) amb Nuxt.js
- API de composició de Vue 3
- Optimització del rendiment