Vuex - Markus Oberlehner - Como Estructurar Un Store Vuex Complejo.docx

  • Uploaded by: Ti Rex Rex
  • 0
  • 0
  • October 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Vuex - Markus Oberlehner - Como Estructurar Un Store Vuex Complejo.docx as PDF for free.

More details

  • Words: 2,076
  • Pages: 11
Document1

1 de 11

How to Structure a Complex Vuex Store Posted on 4 February 2018, by Markus Oberlehner, in Development, tagged JavaScript, Vue and Vuex https://markus.oberlehner.net/blog/how-to-structure-a-complex-vuex-store/

En el artículo de hoy, vamos a echar un vistazo a una posible forma de estructurar una tienda Vuex para una aplicación a gran escala. Cuando estaba investigando posibles enfoques para manejar el estado de las grandes aplicaciones de Vue con Vuex, fue bastante difícil encontrar buenos ejemplos. La mayoría de los ejemplos de Vuex por ahí, están demostrando los conceptos centrales de Vuex, al mostrar cómo construir una aplicación simple, por ejemplo, un carrito de compras muy básico o una lista de tareas pendientes.

Lo que estamos construyendo En este artículo, estamos creando una aplicación simple que consta de dos páginas: 1. en la primera página es posible crear un nuevo cliente y 2. en la segunda página el usuario puede ingresar una dirección de envío. Puede ver una demostración del proyecto aquí (asegúrese de abrir las herramientas de desarrollo de su navegador para ver el resultado de la consola). Además, puedes ver el código completo en GitHub .

Una nueva forma de estructurar una Vuex store. Como no pude encontrar ningún ejemplo de aplicaciones a gran escala que usen Vuex, que son de código abierto, que se ajusten a las necesidades del proyecto en el que estaba trabajando, decidí que podemos resolver el problema a medida que avanzábamos. Al hacerlo, aprendimos muchas cosas, especialmente cómo no hacerlo , pero tal como lo veo, está bien. Una de las mejores cosas de escribir código es que siempre puedes volver y refactorizar cosas. No me gustó cómo resultaron las cosas, así que comencé a pensar en nuevas formas de estructurar una tienda Vuex para satisfacer las necesidades del proyecto.

Document1

2 de 11

El siguiente enfoque es lo que se me ocurrió hasta ahora. src ├── ├── ├── │ │ │ │ │ │ │ │ │ │ └──

App.vue ... store ├── action-types.js ├── index.js ├── modules │ ├── customer.js │ ├── forms │ │ ├── address.js │ │ ├── contact.js │ │ └── name.js │ └── shipping-address.js └── mutation-types.js ...

En el árbol de directorios anterior, puede ver la estructura básica del almacén de Vuex. Echemos un vistazo más de cerca a algunos de esos archivos. // src/store/index.js import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export default new Vuex.Store({ // Making sure that we're doing // everything correctly by enabling // strict mode in the dev environment. strict: process.env.NODE_ENV !== 'production', });

Como puede ver arriba, no hay mucho que hacer en nuestro archivo index.js principal. La razón de esto es que movemos la mayor parte de la lógica a módulos separados. Esto tiene la ventaja de permitir reutilizar ciertas partes del código y también nos permite cargar dinámicamente los módulos Vuex según sea necesario.

Módulos de formulario Para una reutilización máxima, estamos usando módulos de formularios que representan ciertas secciones de nuestros dos formularios. El componente customer form recibe sus datos a partir de tres módulos de formulario: name.js, contact.js y address.js.

Document1

3 de 11

El componente de formulario shipping-address, por otro lado, utiliza solo los módulos de formulario contact.jsy address.js. Los tres módulos de formulario se encuentran en src/store/modules/forms.

El módulo de formulario de contacto. Representante de los otros dos módulos de formulario, que son bastante similares, veremos más de cerca el módulo contact.js de formulario. // src/store/modules/forms/contact.js import { getField, updateField } from 'vuex-map-fields'; import { ADD_ROW } from '../../mutation-types'; import { Contact } from '../../../models/Contact'; const mutations = { updateField, [ADD_ROW](state) { // To enable multi-row form handling // we make it possible to add new rows. state.rows.push(new Contact()); }, }; const getters = { getField, }; // The state must return a function // to make the module reusable. // See: https://vuex.vuejs.org/en/modules.html#module-reuse const state = () => ({ // Pre-fill one row with an // empty `Contact` model. rows: [new Contact()], }); export default { // We're using namespacing // in all of our modules. namespaced: true, mutations, getters, state, };

Document1

4 de 11

Este módulo es responsable de mantener el estado de nuestros campos de formulario relacionados con el contacto ( emaily phone). Esto puede parecer excesivo, pero en los siguientes pasos verá cómo este enfoque granular permite la máxima reutilización.

El módulo de cliente (customer.js) Debido a que el módulo Vuex customer.js es mucho más complicado que los archivos anteriores que hemos visto hasta ahora, para que sea un poco más fácil de explicar y comprender, lo dividiré. // src/store/modules/customer.js import { createHelpers } from 'vuex-map-fields'; // The API util is used to send the // data the user enters to our server. import api from '../../utils/api'; // Models are used to prepare // store data to be sent to an API. import { createCustomer } from '../../models/Customer'; import { createRequest } from '../../models/Request'; import { SUBMIT } from '../action-types'; import { ERROR, SUCCESS } from '../mutation-types'; // We're using reusable form modules // to store the data of our forms. import address from './forms/address'; import contact from './forms/contact'; import name from './forms/name'; // ...

Al principio del archivo, estamos importando todas las dependencias que usaremos en nuestro módulo. No voy a entrar en muchos detalles sobre las cosas que no están directamente relacionadas con la estructura del store. La función importada createHelpers() del paquete vuex-map-fields , se utiliza para manejar campos de formulario con Vuex. Debido a que esta es solo una aplicación de demostración, la utilidad api() es una implementación falsa, que simula una solicitud fallida cada dos veces, para demostrar el manejo de errores y éxito.

Document1

5 de 11

Estamos utilizando modelos para asignar los datos de la tienda a una estructura que podemos enviar a la API. Si desea echar un vistazo más de cerca a esos modelos, puede verificar el código en el repositorio de GitHub .

Actions // src/store/modules/customer.js // ... const actions = { async [SUBMIT]({ commit, state }) { try { const customerData = createCustomer({ // We take only the first row here // because the user is not allowed // to enter more than one address // (or name). address: state.address.rows[0], // Because we allow the user to enter // multiple contacts, we're sending // all rows to the API. contacts: state.contact.rows, name: state.name.rows[0], }); const requestData = createRequest(customerData); await api(requestData); commit(SUCCESS); } catch (error) { commit(ERROR, error.message); } }, }; // ...

La acción SUBMIT, que puede ver arriba, es responsable de enviar los datos ingresados por el usuario a nuestra API y de manejar los estados de error y éxito si la solicitud de API se realiza correctamente o no. Estamos utilizando la función “model helper” createCustomer(), para crear una estructura de datos, que es compatible con lo que nuestra API espera, a partir de los datos almacenados en nuestros módulos de formulario address, contact y name.

Document1

6 de 11

Mutations Necesitamos dos mutaciones para nuestro formulario de cliente:  ERROR, para establecer un estado de error cuando falla la solicitud y  SUCCESS, para hacer prácticamente lo contrario. // src/store/modules/customer.js // ... const mutations = { [ERROR](state, error) { state.error = error; state.success = false; }, [SUCCESS](state) { state.error = false; state.success = true; }, }; // ...

El estado (state) y los módulos. El objeto state es bastante sencillo, estamos definiendo  una propiedad error y  una propiedad success (éxito). En la sección de módulos, especificamos los tres módulos de formulario que se utilizan para almacenar los datos del formulario. // src/store/modules/customer.js // ... const state = () => ({ error: false, success: false, }); const modules = { address, contact, name, }; // ...

Document1

7 de 11

Helper functions Para que sea un poco más conveniente conectar el estado, definido en los módulos de formulario, a los campos de formulario en el componente, estamos exportando las “helper functions” personalizadas de vuex-mapfields. Los usaremos en el siguiente paso cuando construyamos el componente para el formulario del cliente. Al final del archivo, exportamos el objeto customer de nuestro store. // src/store/modules/customer.js // ... // We're exporting custom field mapper // functions for mapping form fields to Vuex. // See: https://github.com/maoberlehner/vuex-map-fields#custom-getters-andmutations export const { mapFields: mapAddressFields } = createHelpers({ getterType: 'customer/address/getField', mutationType: 'customer/address/updateField', }); export const { mapMultiRowFields: mapContactMultiRowFields } = createHelpers({ getterType: 'customer/contact/getField', mutationType: 'customer/contact/updateField', }); export const { mapFields: mapNameFields } = createHelpers({ getterType: 'customer/name/getField', mutationType: 'customer/name/updateField', }); export const customer = { namespaced: true, actions, mutations, state, modules, };

The customer form component Ahora que hemos creado los módulos de nuestro store, es hora de conectar todo. El componente de formulario del cliente PageCustomer.vue es

Document1

8 de 11

responsable de mostrar varios campos de formulario y mensajes de error o de éxito, cuando el usuario envía el formulario. <script> import { createNamespacedHelpers } from 'vuex'; import { SUBMIT } from '../../store/action-types'; import { ADD_ROW } from '../../store/mutation-types'; import store from '../../store'; import { customer, mapAddressFields, mapContactMultiRowFields, mapNameFields, } from '../../store/modules/customer'; // We're dynamically registering the // `customer` store module. This has // the benefit of only loading this // module, if it's actually needed. // Before registering the module, we're // checking if it's already registered // which can happen in combination with // webpacks hot reloading. if (!store.state.customer) { store.registerModule('customer', customer); } const { mapActions: mapCustomerActions, mapState: mapCustomerState, } = createNamespacedHelpers('customer'); const { mapMutations: mapContactMutations, } = createNamespacedHelpers('customer/contact'); export default { name: 'PageCustomer', // Here we're wiring everything up.

Document1

10 de 11

computed: { ...mapCustomerState(['error', 'success']), // You can read more about mapping field // values in two of my previous articles. // https://markus.oberlehner.net/blog/form-fields-two-way-data-bindingand-vuex/ // https://markus.oberlehner.net/blog/how-to-handle-multi-row-formswith-vue-vuex-and-vuex-map-fields/ ...mapNameFields(['rows[0].firstName', 'rows[0].lastName']), ...mapContactMultiRowFields({ contacts: 'rows' }), ...mapAddressFields(['rows[0].zip', 'rows[0].town', 'rows[0].street']), }, methods: { ...mapContactMutations({ addContact: ADD_ROW, }), ...mapCustomerActions({ submit: SUBMIT, }), }, };

Como puede ver arriba, no hay mucha lógica real dentro del componente. La mayor parte de lo que estamos haciendo es mapear acciones, mutaciones y campos de los módulos de la tienda a nuestro componente. Este principio básico de cómo se estructura el store de Vuex se puede escalar a aplicaciones grandes y nos permite reutilizar grandes partes del código de los módulos. Si desea ver la aplicación en acción, puede ir a la demostración en vivo en Netlify y puede ver el código completo en GitHub .

Document1

11 de 11

Resumen Veamos brevemente lo que hemos logrado y cómo este enfoque de estructurar un store Vuex es diferente a los enfoques más tradicionales.

Carga dinámica de módulos. Debido a que no estamos registrando globalmente todos nuestros módulos por adelantado, es posible usar la función de división de código de webpacks en combinación con el vue-router , para cargar componentes de forma dinámica y sus módulos asociados del store. Esto hace que el tamaño del paquete de aplicaciones sea más pequeño, lo que puede tener un gran efecto en el tiempo de carga inicial , especialmente en aplicaciones a gran escala.

Reutilización máxima Diseñar la estructura de nuestro store de una manera que haga que ciertos módulos sean reutilizables, puede tener un enorme impacto positivo en la capacidad de mantenimiento y también en el tamaño del paquete, cuando la aplicación está creciendo. La clave del éxito de esta estrategia, es crear reglas estrictas para nombrar y estructurar sus módulos, de modo que todos se adhieran a una determinada API y se nombren de manera predecible.

Observaciones finales Es cierto que el enfoque que hemos examinado en este artículo está diseñado para resolver un caso de uso muy específico. Es posible que tenga que adaptar ciertos aspectos del mismo a sus propias necesidades. Pero espero que este artículo sirva de inspiración para una solución potente que se adapte a su caso de uso específico.

Related Documents

Markus
May 2020 27
Markus 9
December 2019 24
Store
November 2019 33
Markus 3
December 2019 24
Markus 4
December 2019 29

More Documents from "BandungCOC DataBase"