Potente módulo de escritura Vuex

El motivo para escribir este artículo fue otro artículo sobre la tipificación de Vue y, en consecuencia, Vuex . Para mi sorpresa, no encontré mención de un módulo allí, que, en mi opinión, es el mejor de Vuex de su tipo. Buscar en Habr y, de hecho, en Runet (de hecho, en fuentes en inglés no es fácil encontrar referencias de inmediato), por desgracia, no arrojó ningún resultado. Este artículo no es un análisis detallado y un manual de varias páginas sobre el uso y la configuración, sino más bien una forma de compartir con usted, querido Vue-ninja, una herramienta que hace su trabajo perfectamente.

vuex-smart-module


Quien no tiene tiempo en absoluto: Github .

El objetivo principal del módulo, como habrás adivinado, es la cobertura de formato completo del almacenamiento de Vuex por tipos. Tanto interna como directamente en los componentes mismos. El módulo está escrito por el contribuyente principal ( @ktsn ) de las bibliotecas Vuex y vue-class-component .

Agua


Para admitir, mi camino en Typecript comenzó solo recientemente, incluyendo y con cosas como decoradores, así que no puedo comparar esta biblioteca con otros análogos. Mis intentos de configurar y usar otras herramientas (por ejemplo, decoradores de módulos vuex ) me llevaron a varios problemas, que al final no me permitieron darme cuenta de lo que necesitaba (o simplemente no sabía cómo cocinarlos, como dicen). Tuve mucha suerte con vuex-smart-module : la biblioteca apareció en el mismo momento en que traducía el proyecto (y el repositorio) a Typecript. Ahora todo funciona bien y el código es agradable a la vista.

Ejemplos


La biblioteca, en mi opinión, tiene una buena documentación que cubre todos los casos posibles que encontrará (y si no, en las pruebas puede encontrar todo lo demás, no trivial). Sin embargo, para diluir al menos de alguna manera el artículo con código, daré ejemplos básicos de conexión y uso, un par de ejemplos de "vida", así como también cómo funciona en conjunto con decoradores (hay un matiz allí).

Creación del módulo


Un módulo se crea usando clases. Esto puede parecer inusualmente aterrador para algunos, pero créeme, te acostumbras rápidamente.

store / root.ts

//    import { Getters, Mutations, Actions, Module } from 'vuex-smart-module' //  class RootState { count = 1 } //  //      RootState class RootGetters extends Getters<RootState> { get double() { //      `state` return this.state.count * 2 } get triple() { //       `getters` return this.getters.double + this.state.count } } //  //     ,     RootState class RootMutations extends Mutations<RootState> { increment(payload: number) { //       `state` this.state.count += payload } } //  //     //    ,       ,      class RootActions extends Actions< RootState, RootGetters, RootMutations, RootActions > { incrementAsync(payload: { amount: number; interval: number }) { //      `state`, `getters`, `commit`  `dispatch` return new Promise(resolve => { setTimeout(() => { this.commit('increment', payload.amount) }, payload.interval) }) } } //   export default new Module({ state: RootState, getters: RootGetters, mutations: RootMutations, actions: RootActions }) 

Conexión


/store/index.ts

 import Vue from 'vue' import * as Vuex from 'vuex' import { createStore } from 'vuex-smart-module' import RootStore from './root' Vue.use(Vuex) export const store = createStore( RootStore, { strict: process.env.NODE_ENV !== 'production' } ) 

Módulos


La conexión de módulos es similar a como sucede en Vuex normal. Deben especificarse en la propiedad de módulos de RootStore:

 import FooStore from './modules/foo' /* … */ export default new Module({ state: RootState, getters: RootGetters, mutations: RootMutations, actions: RootActions, modules: { FooStore } }) 

Usar dentro de un componente


Puede usar el stor tanto a través de la propiedad global this. $ Store como a través de la asignación, que es muy similar a la de Vuex:

 import Vue from 'vue' //    (      ) // import FooStore from '@/store/modules/foo' import RootStore from '@/store/root' export default Vue.extend({ computed: RootStore.mapGetters(['double']), methods: RootStore.mapActions({ incAsync: 'incrementAsync' }), created() { console.log(this.double) this.incAsync(undefined) } }) 


Escribiendo


Ejemplo escribiendo commit y dispatch:
 import { categories } from '@/api' export type Category { attributes: { hasPrice: boolean; icon: string lvl: number name: string slug: string }; id: number } export interface IParams { city_id: number } class AppState { categories: Category[] = [] } /* ... */ class AppMutations extends Mutations<AppState> { setCategories(categories: Category[]) { this.state.categories = categories } } class AppActions extends Actions< AppState, AppGetters, AppMutations, AppActions > { async getCategories({params}: {params: IParams}): Promise<Category[]> { return categories.get({params}).then( ({ data }: { data: Category[] }) => { this.commit("setCategories", data) return data } ) } } 


Recepciones


Conéctese usando decoradores ( vue-property-decorator )


 import { Vue, Component } from "vue-property-decorator" //    (      ) // import FooStore from '@/store/modules/foo' import RootStore from "@/store/root" //  ,   ,      Typescript,     : const Mappers = Vue.extend({ computed: { ...RootStore.mapGetters(["double"]) }, methods: { ...RootStore.mapActions({ incAsync: 'incrementAsync' }) } }); @Component export default class MyApp extends Mappers { created() { console.log(this.double) this.incAsync(undefined) } } 

Usar un módulo dentro de un módulo


/store/module/bar.ts

 import { Store } from 'vuex' import { Getters, Actions, Module, Context } from 'vuex-smart-module' //    import FooStore from './foo' /* … */ class BarGetters extends Getters { //   foo!: Context<typeof FooStore>; //     $init(store: Store<any>): void { //     this.foo = FooStore.context(store) } get excited(): string { return this.foo.state.value + '!' // -> hello! } } /* … */ 

Vault reset


A veces puede ser necesario restablecer el almacenamiento a los valores predeterminados, esto se hace simplemente:

 class FooState { /* ... */ } class FooMutations extends Mutations<FooState> { reset () { const s = new FooState() Object.keys(s).forEach(key => { this.state[key] = s[key] }) } } 

Final


Espero que te haya interesado, o al menos te hayas enterado de esta biblioteca. ¿Quién sabe, tal vez comenzar con el próximo proyecto (o tal vez refactorizar los actuales a la vuelta de la esquina?) ¿Usted, como yo, comenzará a usar vuex-smart-module (o TypeScript en general)? Personalmente, mi transición a Typecript fue bastante dolorosa (durante 1.5-2 años, intenté cambiarla al menos 3-4 veces, pero cada vez que tuve algunos problemas, malentendidos. A menudo me atormentaba la sensación de que el desarrollo en Typecript se lleva 2-3 veces más tiempo que antes, porque ahora no puedes simplemente "esbozarlo rápidamente". Pero una vez, al pisar el "lado positivo de la escritura estática", sentí el poder de los tipos y cómo finalmente permiten acelerar el proceso de desarrollo, que es igualmente importante, depurar el código (quizás en el mismo 2- 3 veces), además de facilitar su mayor apoyo.

PD No olvides poner una estrella en este módulo. :)

Gratitud
En conclusión, quiero agradecer a mi amada esposa por su paciencia, al gato por un graznido agradable cerca de la mesa, a los vecinos por el silencio y, por supuesto, por su atención.

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


All Articles