Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save championswimmer/bf17223afcb60fffe8f51bfd56616e82 to your computer and use it in GitHub Desktop.
Save championswimmer/bf17223afcb60fffe8f51bfd56616e82 to your computer and use it in GitHub Desktop.
Writing Vuex modules in neat Typescript classes

Writing Vuex modules in neat Typescript classes

Typescript/ES7 Decorators to make Vuex modules a breeze

Installation

npm install -D vuex-module-decorators

Babel 6/7

  1. You need to install babel-plugin-transform-decorators

Typescript

  1. set experimentalDecorators to true
  2. For reduced code with decorators, set emitHelpers: true and importHelpers: true

Usage

The conventional old & boring way

Remember how vuex modules used to be made ?

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

Hello Decorators !

Well not anymore. Now you get better syntax. Inspired by vue-class-component

import {Module, VuexModule, Mutation, Action} from 'vuex-module-decorators' 

@Module
export default class Counter2 extends VuexModule {
  count = 0

  @Mutation increment(delta: number) {this.count+=delta}
  @Mutation decrement(delta: number) {this.count-=delta}

  // action 'incr' commits mutation 'increment' when done with return value as payload
  @Action({commit: 'increment'}) incr() {return 5}
  // action 'decr' commits mutation 'decrement' when done with return value as payload
  @Action({commit: 'decrement'}) decr() {return 5}
}

async MutationAction === magic

Want to see something even better ?

import {Module, VuexModule, MutationAction} from 'vuex-module-decorators'
import {ConferencesEntity, EventsEntity} from '@/models/definitions' 

@Module
export default class HGAPIModule extends VuexModule {
  conferences: Array<ConferencesEntity> = []
  events: Array<EventsEntity> = []

  // 'events' and 'conferences' are replaced by returned object
  // whose shape must be `{events: {...}, conferences: {...} }`
  @MutationAction({mutate: ['events', 'conferences']})
  async fetchAll () {
    const response: Response = await getJSON('https://hasgeek.github.io/events/api/events.json')
    return response
  }
}

Automatic getter detection

@Module
class MyModule extends VuexModule {
  wheels = 2

  @Mutation
  incrWheels(extra) {
    this.wheels += extra
  }

  get axles() {
    return (this.wheels / 2)
  }

}

this is turned into the equivalent

const module = {
  state: {wheels: 2},
  mutations: {
    incrWheels(state, extra) {
      state.wheels += extra
    }
  },
  getters: {
    axles: (state) => state.wheels / 2
  }
}

Putting into the store

Use the modules just like you would earlier

import Vue from 'nativescript-vue';
import Vuex, {Module} from 'vuex'

import counter from './modules/Counter2';
import hgapi from './modules/HGAPIModule'

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {},
  modules: {
    counter,
    hgapi
  }
});

Written with StackEdit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment