Vuex: estructurando grandes proyectos y trabajando con módulos

Vuex es una biblioteca de administración de estado de aplicación oficial y bien documentada diseñada específicamente para Vue.js. El autor del material, cuya traducción publicamos hoy, cree que usar esta biblioteca es mucho más agradable que Redux, porque, en primer lugar, Vuex requiere menos código repetitivo y, en segundo lugar, porque funciona con mecanismos asincrónicos, no se necesitan bibliotecas adicionales aquí. Además, dado que la biblioteca Vuex fue creada por el mismo equipo que está trabajando en Vue, esta biblioteca se integra muy bien con este marco. Desafortunadamente, al trabajar con Vuex aún puede encontrar una dificultad, que consiste en preparar adecuadamente la estructura de los proyectos en los que planea utilizar esta biblioteca.



En este artículo encontrará una descripción de la metodología para estructurar grandes proyectos utilizando Vuex, y un script diseñado para automatizar el proceso de creación de módulos Vuex.

Vue-enterprise-boilerplate patrón y problema de estructura del proyecto


Uno de los desarrolladores de Vue, Chris Fritz, creó una plantilla excelente para Vue, la estructura del proyecto presentada en la cual está diseñada para usar Vuex. En particular, esta plantilla permite que Vuex registre automáticamente módulos basados ​​en los archivos en la carpeta de modules . La estructura de carpetas del proyecto puede parecerse a la siguiente figura.


Estructura del proyecto y colocación de código inconveniente

Al usar esta plantilla, es necesario que el estado, captadores, acciones y mutaciones estén en el mismo archivo. Personalmente, prefiero guardarlos en archivos separados, lo que permite, dado el hecho de que los módulos Vuex a veces son bastante grandes, es conveniente navegar por los programas, sin tener que desplazarse a través de grandes fragmentos de código. Siguiendo esta idea, cambiaremos el código de la plantilla para que lo que se relaciona con módulos individuales se pueda clasificar en carpetas destinadas a estos módulos. Es decir, la estructura del proyecto cambiará y será similar a la que se muestra a continuación.


La estructura del proyecto con el desglose de los materiales de los módulos en archivos separados que se encuentran en las carpetas de los módulos.

Desarrollo de una plantilla que soporte una estructura de proyecto conveniente.


Entonces, vamos a organizar el trabajo con Vuex para que podamos usar estructuras de carpetas y archivos similares a las mostradas en la figura anterior en nuestros proyectos. Para hacer esto, primero cree un nuevo proyecto usando Vue CLI 3 .

Después de tener una plantilla de proyecto lista para seguir trabajando con ella, instale Vuex y Lodash ejecutando el npm install vuex lodash -save en el terminal. Para trabajar con módulos, necesitamos la función camelCase de Lodash, que está diseñada para convertir cadenas al estilo camel.

Ahora cree una carpeta y una estructura de archivo similar a la que se muestra en la figura anterior.

Comencemos con el archivo store.js . Aquí está su código:

 import Vue from 'vue' import Vuex from 'vuex' import modules from './modules' Vue.use(Vuex) const store = new Vuex.Store({ modules, strict: process.env.NODE_ENV !== 'production' }) //    `init`     for (const moduleName of Object.keys(modules)) { if (modules[moduleName].actions.init) {   store.dispatch(`${moduleName}/init`) } } export default store 

Vue y Vuex se importan aquí, ya que no podemos prescindir de ellos. Además, importamos módulos desde /modules/index.js . A continuación, inicializamos el almacenamiento y recorremos todos los módulos. Si el módulo tiene una acción init , inicializamos el módulo. Esto resulta ser muy útil para aquellos módulos que deben inicializarse cuando se inicia la aplicación. Como resultado, por supuesto, exportamos la store , después de lo cual, generalmente, se importa al archivo main.js y se agrega a la instancia de Vue.

Ahora es el momento de trabajar con el archivo index.js , que se encuentra en la carpeta /store/modules .

 //    Vuex     ,    . import camelCase from 'lodash/camelCase'; //    const requireModule = require.context( //      '.', //     true, //   index.js,    ,    //   'actions', 'mutations',  'getters' . //  ,      .js /^(?!.*(actions|mutations|getters|index)).*\.js$/ ); const modules = {}; requireModule.keys().forEach(fileName => { //     if (/\.unit\.js$/.test(fileName)) return; //            modules[camelCase(fileName.split('/')[1].replace(/(\.\/|\.js)/g, ''))] = {   namespaced: true,   ...requireModule(fileName).default }; }); export default modules; 

En este código, primero importamos la función camelCase de Lodash. Luego usamos el método require.context para conectar los módulos. Como tercer parámetro, pasamos una expresión regular que filtrará el archivo index.js , así como los archivos cuyos nombres contienen las actions líneas, mutations y getters . Se importarán al archivo de estado, por ejemplo, en auth.js , y luego se exportarán. Por ejemplo, así es como auth.js archivo auth.js carpeta src/store/modules/auth/ al comienzo del trabajo:

 import actions from './actions'; import mutations from './mutations'; import getters from './getters'; const state = {   user: null }; export default {   state,   mutations,   getters,   actions }; 

Ahora solo queda pasar por todos los módulos y formar un solo objeto con todos ellos. Aquí debe excluir todos los archivos en cuyo nombre hay una unit línea, ya que son necesarios solo para pruebas y no para desarrollo o para implementar un proyecto en producción. Después de eso, agregamos una nueva propiedad al objeto de modules , que tendrá el nombre del archivo de estado, por ejemplo, auth o users . Además, utilizamos la función camelCase para hacer que los nombres de propiedades se vean consistentes. Luego requireModule el objeto de modules , requireModule través del requireModule y usando la ...requireModule(fileName).default , y luego exportamos los modules .

De hecho, así es como un proyecto puede estructurarse en qué estado, captadores, acciones y mutaciones se almacenan por separado y se organizan convenientemente. Ahora hablemos sobre cómo escribir un script para crear automáticamente módulos Vuex.

Script para crear automáticamente módulos Vuex


Cree una nueva carpeta en la carpeta del proyecto con los scripts nombre, en ella cree el archivo generateVuexModule.js . Para este proyecto necesitaremos Node.js, por lo tanto, si no tiene esta plataforma instalada, ahora es el momento de solucionarlo . Nuestro script tiene una sola dependencia: el paquete de chalk , que se utiliza para diseñar materiales que se muestran en la consola. Puede instalar este paquete con el npm install -save-dev chalk .

▍Paso 1


En el archivo generateVuexModule.js , debe conectar tres módulos: fs , path y chalk . También aquí necesita una constante con la ruta a la carpeta de módulos ( src/store/modules ) y otra constante - args , que hará que los argumentos pasen al script cuando se ejecutó.

 const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const modulesPath = 'src/store/modules'; const args = process.argv.slice(2); const error = (...args) => { console.log(chalk.red(...args)); }; const success = (...args) => { console.log(chalk.green(...args)); }; if (!args.length) { error('You must provide a name for the module!'); return; } 

Como puede ver, escribimos todos los argumentos en los argumentos excepto los dos primeros, ya que representan la ruta a node.exe y el archivo de script, y no necesitamos esta información. Solo nos interesa el tercer parámetro: el nombre del nuevo módulo. Además, hay un par de funciones, error y success , que utilizan el paquete de chalk antes mencionado para mostrar mensajes con textos de diferentes colores.

Aquí debe verificar la longitud de la matriz args para saber si el nombre del módulo se pasa a nuestro script y, si no es así, dar un mensaje de error. Por lo tanto, si intenta ejecutar este script usando el comando node generateVuexModule.js del node generateVuexModule.js , sin pasarle nada más, verá un mensaje de error en el terminal.

▍Paso 2


En este punto, tenemos un nombre para el módulo y la ruta dada por la constante modulesPath . Sin embargo, todavía tenemos que trabajar con estos datos. Es decir, extraiga el nombre de la matriz de args y recopile la ruta completa al módulo, sin mencionar la formación de su contenido.

 const moduleName = args[0]; const modulePath = path.join(__dirname, '../', modulesPath, moduleName); if (fs.existsSync(modulePath)) { error(`${moduleName} directory already exists!`); return; } const stateContent = `import getters from './getters'; import actions from './actions'; import mutations from './mutations'; const state = {}; export default { state, getters, actions, mutations }; `; const exportFileContent = `import * as types from '@/store/types'; export default { }; `; 

El nombre del módulo estará en el elemento de la matriz de args con índice 0. En esta etapa del programa, podemos contar con la presencia de este elemento, ya que previamente intentamos extraerlo de process.argv , y luego verificamos la longitud de la matriz de args . Además, preparamos la ruta completa utilizando el módulo de path y el método de join . Obtuvimos el directorio actual usando la construcción __dirname , __dirname un nivel, ya que el archivo generateVuexModule.js se encuentra en la carpeta del proyecto de scripts . Luego simplemente agregamos al resultado, el contenido de la modulesPath constante y el nombre del módulo. En este punto, la constante modulePath debe contener algo como pathToYourProject/project/src/store/modules/moduleName . Aquí es donde se creará el módulo. Ahora, dado que tenemos la ruta completa, podemos verificar si este directorio existe. No quisiéramos sobrescribir accidentalmente los archivos de un módulo existente. Como resultado, si el directorio en el que planea crear un nuevo módulo existe, mostraremos un mensaje de error en letras rojas, gracias a chalk .


Ejemplo de mensaje de error

A continuación, debe crear constantes en las que habrá datos para los archivos. Como puede imaginar, stateContent usa para el archivo de estado, es decir, por ejemplo, para auth.js , y exportFileContent se usa para getters.js , getters.js y mutations.js . Si es necesario, puede agregar a esta lista todo lo que se requiere en su proyecto.

▍Paso 3


Ahora solo tenemos que crear rutas para los archivos del módulo y crearlas.

 const statePath = `${path.join(modulePath, `${moduleName}.js`)}` const gettersPath = `${path.join(modulePath, 'getters.js')}` const actionsPath = `${path.join(modulePath, 'actions.js')}` const mutationsPath = `${path.join(modulePath, 'mutations.js')}` fs.mkdirSync(modulePath); fs.appendFileSync(statePath, stateContent); fs.appendFileSync(gettersPath, exportFileContent); fs.appendFileSync(actionsPath, exportFileContent); fs.appendFileSync(mutationsPath, exportFileContent); success('Module', moduleName, 'generated!'); 

Primero declaramos cuatro constantes, cada una de las cuales contiene una ruta para el archivo correspondiente. A continuación, necesitamos crear una carpeta para el módulo. Ya verificamos si existe dicha carpeta y le dimos un error si es así. Por lo tanto, no debería haber problemas con la creación de una carpeta. Y finalmente, usamos los fs.appendFileSync , colocando los nuevos archivos con los contenidos especificados en el proceso de creación en el directorio recién creado. Al final, el script muestra un mensaje sobre la finalización exitosa de la operación.

Para usar este script, simplemente vaya a la carpeta de scripts de su proyecto en la terminal y ejecute un comando del node generateVuexModule.js yourModuleName formulario node generateVuexModule.js yourModuleName . Después de completar con éxito el script, verá un mensaje sobre la creación de un módulo.

Resumen


Después de revisar este material, aprendió sobre una plantilla para estructurar proyectos grandes donde planea usar Vuex, y un script que simplifica la creación de módulos Vuex. Esperamos que encuentre útil este conocimiento. El código del proyecto, cuyos ejemplos examinamos, se puede encontrar aquí .

Estimados lectores! ¿Cómo estructuran las grandes aplicaciones de Vue que usan Vuex?

Source: https://habr.com/ru/post/es420357/


All Articles