First we need to create a new Vue 3 project, we are going to use Vue CLI create command to create a new Vue 3 project, select Default options for Vue 3
vue create vue-3-vuex
cd vue-3-vuex
This is a list of all the packages needed and the reason why we will install them:
"vuex" (npm install vuex --save): Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.
npm install vuex --save
Next we will initialize our application if everything was successfully you should see the Vue application on http://localhost:8080/
npm run serve
First we are going to create a store with different modules, create a new folder called store inside the src folder, now create a folder called main inside our new store directory, this will be our main module we can create new modules by creating new folders with our module specific name, for example user, if we wanted to contain all user logic in a specific module. Each module will contain 5 files (actions.js, getters.js, index.js, mutations.js, state.js), in this case I'm going to show you an example of each file using our main Module
// src/store/main/state.js
// Will contain all the current values for the state of this module
let state = {
pokemons: [],
message: "Pokemons module message"
};
export default state;
// src/store/main/getters.js
// Will contain getters to obtain the current values from the state variables in this module
let getters = {
/**
* Gets pokemon from state
*/
POKEMONS: (state) => {
return state.pokemons;
},
/**
* Gets message from state
*/
MESSAGE: (state) => {
return state.message;
},
};
export default getters;
// src/store/main/mutations.js
// Will contain all the mutations or functions that will alter the state of this module
let mutations = {
/**
* Sets pokemon state variable to the array received on payload results
*/
SAVE_POKEMONS: (state, payload) => {
state.pokemons = payload;
},
};
export default mutations;
// src/store/main/actions.js
// Will contain all actions of this module
let actions = {
/**
* Example action fetching Pokemons data and saving it on the state, using a mutation
*/
GET_POKEMONS: (context) => {
return new Promise((resolve, reject) => {
fetch(`https://pokeapi.co/api/v2/pokemon?limit=150`)
.then(response => response.json())
.then(pokemons => {
context.commit("SAVE_POKEMONS", pokemons.results);
resolve(pokemons.results);
}).catch((err) => {
reject(err);
});
});
},
};
export default actions;
// src/store/main/index.js
// Will export our module with all the actions, getters, mutations and the state
import actions from "./actions";
import getters from "./getters";
import mutations from "./mutations";
import state from "./state";
let main = {
state,
actions,
mutations,
getters,
};
export default main;
now we are going to export our store modules in the base file of our store
// src/store/index.js
// Will export all our modules
import Vuex from "vuex";
import main from "./main";
export default new Vuex.Store({
modules: {
main,
},
});
Now search for the main.js file inside the src folder, this is the place where we will add our store to our Vue application
import { createApp } from 'vue'
import App from './App.vue'
// Import store entry file
import store from "./store";
const app = createApp(App);
// Tell created vue app to use our store with all it's modules
app.use(store);
app.mount("#app");
Now we can interact with our store in any Vue component, we will use the HelloWorld.vue component inside the components folder to display a list with the message in our main module and a list with the pokemons we got from our action
<template>
<div class="hello">
<h1>{{ message }}</h1>
</div>
<div class="pokemons-container">
<ul>
<li v-for="pokemon in pokemons" :key="pokemon.name">
{{pokemon.name}}
</li>
</ul>
</div>
</template>
<script>
// Import functions needed from vue
import { computed, onMounted } from "vue";
// Import composition API function to access store
import { useStore } from "vuex";
export default {
// Component name
name: "HelloWorld",
// Composition API setup
setup() {
// Composition API function to access store
const store = useStore();
// Get message from store as computed property to trigger rendering on property changes
let message = computed(() => store.getters["MESSAGE"]);
/**
* Get pokemons from store as computed property to trigger rendering on property changes
* be carefull when having objects arrays inside of objects, computed properties won't trigger
* rendering if one of the properties of an object of the array changes only if the whole array is
* changed
*/
let pokemons = computed(() => store.getters["POKEMONS"]);
/**
* @desc dispatch action to get pokemons from API
*/
const getPokemons = async () => {
// Dispatch GET_POKEMONS action without payload
await store.dispatch("GET_POKEMONS", {});
// Print value of pokemons in store
console.log(pokemons.value)
};
/**
* Run functionality on component mount
*/
onMounted(() => {
// Get pokemons
getPokemons().then(() => {})
});
return {
message,
pokemons,
};
},
};
</script>
<style scoped>
</style>
In this repository https://github.com/obravocedillo/Vue3Vuex you can find the code.