easy-vuex-modules

Vuex helper that makes working with modules easier and more organized.

Usage no npm install needed!

<script type="module">
  import easyVuexModules from 'https://cdn.skypack.dev/easy-vuex-modules';
</script>

README

easy-vuex-modules

Vuex helper that makes working with modules easier and more organized.

Install

npm install easy-vuex-modules
or
yarn add easy-vuex-modules

Example implementation:

https://github.com/plakak/easy-vuex-modules/tree/master/example

What problem does it solve?

When using namespaced modules in Vuex, mappings of mutations/actions/getters are string based arrays:

...mapActions([
   'some/nested/module/foo', // -> this['some/nested/module/foo']()
   'some/nested/module/bar' // -> this['some/nested/module/bar']()
])

and mapping of state requires using functions:

 ...mapState({
    a: state => state.some.nested.module.a,
    b: state => state.some.nested.module.b
  })
},

There's also an option to go with const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') when it's needed but this adds even more code in each component.

easy-vuex-modules provides a set of helpers with it's own mapState, mapGetters... that makes using modules a bit more straightfowrad.

mapState

But if you'd like to follow string pattern that mapState allows when no namespaces are used - easy-vuex-modules allows just that. Handling of the mapState via native vVex function is very dencent. You don't rely on strings and that's the benefit. But if you'd like to follow string pattern that mapState allows when no namespaces are used - easy-vuex-modules allows just that.

Before:

    ...mapState({
       a: state => state.some.nested.module.a,
       b: state => state.some.nested.module.b
     })
   },

After:

The state with easy-vuex-modules resolves pretty straighforward - yyou can provide a string like you would if there was no namespaces at all.

import { mapState } from `easy-vuex-modules`;

...mapState([
   'some.nested.module.a',
   `some.nested.module.b`
]),

mapGetters, mapMutations, mapActions

The real power of easy-vuex-modules shows here. While defining a state user also defines a namespaceMap that later allows to resolve getters/mutations/actions without use of error-prone strings. namespaceMap is a simple object with names that are used throught the store. You'll see how to build it in next section.

Before:

...mapActions([
   'some/nested/module/foo', // -> this['some/nested/module/foo']()
   'some/nested/module/bar' // -> this['some/nested/module/bar']()
])

After:

 import { mapGetters, mapMutations } from `easy-vuex-modules`;
 import { module1, module2 } from './store';

 export default {
   name: 'App',
   computed: {
     ...mapGetters([
       module1.getters.foo,
       module2.getters.bar
     ])
   },
   methods: {
     ...mapMutations([
       module1.mutations.updateFoo
     ]),
     ...mapActions([
       module2.actions.changeBar
     ])
   }
 };

Base usage

  • Start by defining a namespace for a given module
export const myModuleNamespace = {
   module: 'myModule',
   getters: {
     foo: 'foo'
   },
   mutations: {
     bar: 'bar',
   },
   actions: {
     baz: 'baz'
};
  • When creating a module, use defined namespace values as keys
export const myModule = {
  state: {
    data: 1
  },
  getters: {
    [myModuleNamespace.getters.foo](state) {
      // getter
    }
  },
  mutations: {
    [myModuleNamespace.mutations.bar](state) {
      // mutation
    },
  actions: {
   [myModuleNamespace.actions.baz](state) {
        // action
    }
   }
  }
};
  • During store creation make sure you use namespace for each module, or just use namespace helper provided by the library
import { namespace } from 'easy-vuex-modules';
import { myModule } from './myModule';
 
export const storeInstance = new Vuex.Store({
  modules: namespace({
    myModule: myModule,
  })
});
  • The step where magic happens. Use createModuleMap on the module namespace and export the result for use inside the components
import { namespace } from 'easy-vuex-modules';
import { myModule } from './myModule';
 
export const storeInstance = new Vuex.Store({
  modules: namespace({
    myModule: myModule,
  })
});

export const counterOne = createModuleMap(counterOneNamespace);
  • Import your store normally into the app import store from './store';
import { storeInstance } from './store';

new Vue({
  el: '#app',
  store: storeInstance,
  render: h => h(App),
});
  • Use easy-vuex-modules functions instead of native vuex functions when mapping in component
  import { mapGetters, mapMutations, mapActions } from 'easy-vuex-modules';
  import { myModule } from './store';

  export default {
    name: 'App',
    computed: {
      ...mapGetters([
        myModule.getters.foo
      ])
    },
    methods: {
      ...mapMutations([
        myModule.mutations.bar,
      ]),
      ...mapActions([
        myModule.actions.baz      
      ])      
    }
  };

Now you no longer have to use long strings to map to namespaced modules and if your IDE is clever enough it will even suggest you autocomplete for keys (this should even work better after I add typings to the library)

Running example

Repository includes a simple example that can be easly run with webpack via yarn run example command.

Dependences

  • Vuex

Compatibility

easy-vuex-modules depends on Proxy functionality being available. Browser without Proxy support are not supported.

TODO:

  • add tests
  • add typings