Ampliando conocimientos de VueX: módulos

Posted by in Javascript y TypeScript

En la tercera entrada de la serie Trabajando con Vuetify (parte 2) os hablé de VueX, el repositorio de información utilizado para trabajar con VueJS, y que es de lo más práctico (en mi opinión). Hoy ampliamos conocimientos con el uso de módulos de VueX.

VueX en grandes proyectos

Aunque en el título he puesto VueX para grandes proyectos, las explicaciones que te describo a continuación también sirven para proyectos de tipo medio, o incluso proyectos pequeños. No hay una receta perfecta, pero lo que yo te cuento aquí está basado absolutamente en mi experiencia, y en lo que me ha funcionado.

Cuando yo trabajo en algún proyecto, con independencia del trabajo, suelo disponer de la siguiente organización:

  • API: donde se desarrolla la API de la aplicación
  • components: son componentes que suelo reutilizar en varios proyectos. Aquí incluyo, por ejemplo, cajas de mensajes, o cajas para preguntar a los usuarios, login, …
  • components2: son los componentes exclusivos del proyecto
  • css: aquí incluyo todas las hojas de estilo de la aplicación
  • img: para las imágenes
  • js: para las librerías Javascript, en caso de que las necesites disponer de forma local (en lugar de llamar a CDN)
  • mixins: aquí tengo los archivos de Javascripts que utilizo como mixins para todo el proyecto, tanto para components2 como store2
  • routes: aquí para trabajar con vue-router (aún no lo hemos trabajado)
  • store: archivos que forman el store que se comparten con varios proyectos
  • store2: archivos que forman el store de la aplicación
  • utils: otros ficheros Javascript que puedan hacerme falta

Dado que la gran mayoría de desarrollos que realizo lo hago contra bases de datos, a su vez, es posible que dentro de cada directorio exista un subdirectorio por cada tabla. Esto es así en API, mientras que suelo desarrollar en cada fichero los componentes específicos para cada tabla, y los incluyo todos.

Por ejemplo, si tengo una tabla provincias, en el directorio api tengo un directorio, tengo un archivo en store2 llamados provincias.js y a su vez, otro provincias.js en components2.

Con el paso del tiempo, he ido creando una serie de componentes básicos que reutilizo muy frecuentemente: por ejemplo, para tablas diccionario, tengo uno exclusivo.

Supongo que tú, mi querido lector, también terminarás siendo cuidadoso a la hora de estructurar los proyectos, y aquí te he contado mi forma.

Siguiendo con el store, te cuento cómo preparo un módulo.

El módulo test.js en Vuex

Cuando se complica el store porque la información a almacenar es amplia o queremos distribuir mejor la información, existe la posibilidad de usar módulos, lo que permite ordenar dicha información. Y es lo que se ha hecho con store/test.js, que es un módulo que se ha añadido.

Los módulos también incluyen su store, getters, actions y mutations, y aunque parezca complicado de entender, es la base para trabajar con aplicaciones no tan básicas.

El código de store/test.js es:

// Vuex test 1.3.6 - 20200702

// Constantes 
const test_null = {};
const test_search_null = {};

const test_actions = {
	listing: async function({commit, getters, rootState, rootGetters, dispatch}, query) {
		// include API calls
	},
	view: async function({commit, getters, rootState, rootGetters, dispatch}, query) {
		// include API calls
	},
};

const test_state = {
	base: {
		tabla: 'test', 	// CONFIG - Tabla
		campo_id: 'idcanon', // CONFIG - Campo ID
	},
	search: test_search_null,
	regs: [],
	num_regs: 0,
	registro: null,
};

const test_getters = {
	error: state => `${state.base.tabla}`,
	table: state => state.base.tabla,
	campo_id: state => state.base.campo_id,
	// raw: state => state.raw,
};


const test_mutations = {
	num_regs: set('num_regs'), // set para asignacion SIMPLE
	regs: setbase('regs'),  // setbase para incluir
	registro: setbase0('registro'),
	clear(state) {
		state.registro = test_null;
		state.regs = [];
		state.num_regs = 0;
	},
	clean(state) {
		state.registro = test_null;
	},
	reset(state) {
		// state.search.campo_i = 0;
		// state.search.campo_s = '';
	},
	// Exclusivas de test
	// campo_i: function(state, val) { state.search.campo_i = val; },
	// campo_s: function(state, val) { state.search.campo_s = val; },
};

const test = {
	namespaced: true,
	state: test_state,
	mutations: test_mutations,
	getters: test_getters,
	actions: test_actions
};

Básicamente, para el desarrollo de un módulo de store suelo desarrollar variables con nombres muy determinados para el desarrollo de lo que necesito (y que varía, o puede hacerlo, de un módulo a otro). Al final, creo una variable, en este caso es test, donde asocio los estados, acciones, mutations y getters. Además, esa variable test es la que hay que incluir en la declaración del state.

Además, se incluye la propiedad namespaced, que cuando está a true, es porque quiero que el tratamiento por parte de VueX sea cómo un módulo, y por tanto, las llamadas desde fuera serán tal que así:

  • dispatch(‘test/listing’)
  • commit(‘test/registro’, {})

Pero aún falta un paso más, y es preparar el store para que pueda utilizar el módulo. En este caso, volvermos sobre store/_index.js y lo modificamos tal que así:

const store = new Vuex.Store({
	strict: true, // en development
	state,
	getters,
	mutations,
	modules: { // Your store-modules
		test,
	}
})

Una ayuda para el store: state-mutators.js

Cuando estaba aprendiendo sobre VueX me encontré con esta entrada dónde hacían unas recomendaciones para facilitar el trabajo de las mutations, y que al final, he ido ampliando según mis propias necesidades. Y por tanto, también será necesario cargar, ya que precisamente este es uno de los archivos que tengo en el directorio utils.

En relación con el proyecto de Trabajando con VueX, a pesar de haber cargado varios archivos de Javascript y ampliado el Store, aún no hemos usado nada. Lo veremos más adelante!

Mi opinión sobre VueX

Sinceramente, VueX me parece casi de uso obligatorio en cualquier proyecto de VueJs que implique trabajar con datos, y aunque pueda parecer lioso, te aseguro que está muy bien pensado, y funciona, y el hecho de que sea estricto y requiera un flujo de trabajo concreto hace que cometer fallos sea más difícil.

Con el paso del tiempo, al final he ido desarrollando también variables específicas para trabajar con VueX que aceleran mucho el desarrollo ya que me han permitido reutilizarlas en muchos sitios, y disponer de una estructura bastante fiable, dónde tengo mucho preparado de antemano. Además, la detección de errores hace que cuando se corrija, éste esté automáticamente corregido en todos los sitios donde se utilizan, pero además, me permite ampliar con opciones en el caso de que sea necesario, en un solo sitio, quedando a disposición para el resto de proyectos.

Y poco más. Te animo a que aprendas a trabajar con los módulos de VueX que son muy útiles, sobre todo cuando el tamaño de los proyectos crece.

Happy coding!