Vuex, manejador de estados en Vue, como Redux en ReactJS
Vuex es un patrón de gestión de estado para aplicaciones Vue.js. Sirve como una tienda centralizada para todos los componentes de una aplicación, con reglas que aseguran que el estado solo pueda mutarse de manera predecible
¿Qué es un “patrón de gestión del estado”?
La administración del estado puede verse como la capacidad de administrar datos compartidos entre componentes múltiples y a menudo no relacionados.
Esta es la idea básica detrás de Vuex, inspirada en Flux, Redux y The Elm Architecture. A diferencia de los otros patrones, Vuex también es una implementación de biblioteca diseñada específicamente para Vue.js para aprovechar su sistema de reactividad granular para actualizaciones eficientes.
En el centro de cada aplicación Vuex está el store. Un “store” es básicamente un contenedor que contiene el estado de su aplicación. Hay dos cosas que hacen que una store Vuex sea diferente de un objeto global simple:
Los store Vuex son reactivas. Cuando los componentes de Vue recuperan el estado, se actualizarán de manera reactiva y eficiente si cambia el estado de el store.
No puede mutar directamente el estado del store. La única forma de cambiar el estado del store es mediante la confirmación explícita de mutaciones. Esto garantiza que cada cambio de estado deje un registro rastreable y habilite herramientas que nos ayuden a comprender mejor nuestras aplicaciones.
Aplicación del patrón de gestión de estados en el desarrollo de un Login
//Contiene los métodos de loguin
import UserService from '@/core/services/user.service';
import router from '@/core/router';
//Obtener el usuario guardado en el local storage
//Significa que se tiene la información de la sessión existente
//(userID, token de acceso, etc.)
const user = JSON.parse(localStorage.getItem('user'));
//Definición del estado inicial
const initialState = user
? { status: { loggedIn: true }, user }
: { status: {}, user: null };
//Definición del store
export const authentication = {
//Esta opción es para poder diferencia este store del resto
//y hacer referencia a este en los componentes a través de su nombre
namespaced: true,
//Inicializar estado iniciar
state: initialState,
//Definir las acciones
//Estas son invocadas desde los componentes para cambiar el estado de las variables definidas
//en el initialState
actions: {
login({ dispatch, commit }, { username, password }) {
//La llamada del metodo commit ejecuta una mutación
//Donde se le pasa el identificador de la mutación
//y los nuevos valores de los state (si son requeridos)
commit('loginRequest', { username });
let userService = new UserService()
//Llamada al servicio de login
userService.login(username, password)
.then(
user => {
commit('loginSuccess', user);
router.history.push('/');
},
error => {
commit('loginFailure', error);
}
);
},
logout({ commit }) {
let userService = new UserService()
userService.logout();
commit('logout');
}
},
//Mutaciones son las encargadas de cambiar el valor a los state
mutations: {
loginRequest(state, user) {
state.status = { loggingIn: true };
state.user = user;
},
loginSuccess(state, user) {
state.status = { loggedIn: true };
state.user = user;
},
loginFailure(state) {
state.status = {};
state.user = null;
},
logout(state) {
state.status = {};
state.user = null;
}
}
}
Este sería el servicio de login
import Service from './base.service'
export default class UserService {
constructor() {
this.service = new Service()
}
login(username, password) {
return this.service.post(`account/signin`, { username: username, password: password, remember: true })
.then(response => {
if (response.data.access_token) {
localStorage.setItem('user', JSON.stringify(response.data));
}
return response.data
});
}
logout() {
let user = JSON.parse(localStorage.getItem('user'))
return this.service.post(`account/signout?r=${user.access_token}`,{})
.then(response => {
if (response.data.access_token) {
localStorage.removeItem('user');
}
return response.data
});
}
}
A continuación el componente Login
<template>
<v-app id="inspire">
<v-content>
<v-container class="fill-height" fluid>
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<v-card class="elevation-12">
<v-toolbar color="primary" dark flat>
<v-toolbar-title>Login form</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card-text>
<v-form>
<v-text-field
label="Login"
name="email"
v-model="email"
prepend-icon="person"
type="text"
></v-text-field>
<v-text-field
id="password"
label="Password"
name="password"
v-model="password"
prepend-icon="lock"
type="password"
></v-text-field>
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn v-on:click="login" color="primary">Login</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</template>
<script>
export default {
data() {
return {
email: "",
password: ""
};
},
computed: {
loggingIn() {
//Accesso global a los state de la aplicación
return this.$store.state.authentication.status.loggingIn;
}
},
methods: {
login: function() {
const email = this.email;
const password = this.password;
this.$store
.dispatch("authentication/login", { username: email, password })
.then(() => {
//this.$router.push('/')
});
}
}
};
</script>
En fin primero se define el store del módulo dentro de la aplicación con los estados iniciales que responden a las variables que se usan dentro de un componente y que mediante la interacción del usuario pueden cambiar de valor, dentro del store se definen las actions con son las que se invocan desde el componente para cambiar el valor a un state parandole los valores requeridos:
this.$store
.dispatch(“authentication/login”, { username: email, password })
y finalmente mediante el método commit se ejecuta una mutations para hacer efectivo el cambio de estado.
Espero te sea útil, si crees que así fue puedes invitarme un café y/o dejar tus comentarios.
Excellent articule fits my needs a lot, in the end I understand the operación of Redux and the states