š© Vuex Pattern: Smart Module Registration
Nikos Koikas
Posted on July 30, 2018
Vue Experience: ā«ļøā«ļøā«ļøā«ļøāŖļø
Vuex Experience: ā«ļøā«ļøā«ļøā«ļøā«ļø
Have your ever tried to manage your's application state?
Large applications can often grow in complexity, due to multiple pieces of state scattered across many components and the interactions between them. So, Vue offers Vuex but as official documentation says:
Vuex is using a single state tree, all state of our application is contained inside one big object. However, as our application grows in scale, the store can get really bloated.
To help with that, Vuex allows us to divide our store into modules. Each module can contain its own state, mutations, actions, getters, and even nested modules.
I think you have already got confused, so let's go into code.
# This is a classic store structure with modules
āāā index.html
āāā main.js
āāā components
āāā store
āāā index.js # where we assemble modules and export the store
āāā modules
āāā auth.js
āāā posts.js
āāā comments.js
As you can see we have a store folder with an index.js
and a subfolder named modules
, which contains all modules. But module registration can start to get tedious.
index.js
in store/
import Vue from 'vue'
import Vuex from 'vuex'
import auth from './modules/auth'
import posts from './modules/posts'
import comments from './modules/comments'
// ...
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
auth,
posts,
comments,
// ...
}
})
Example scaffolding for Vuex modules.
export default {
namespaced: true,
state: {},
getters: {},
mutations: {},
actions: {}
}
This is the standard way for registering modules. If you know what namespacing is, go on.
By default, actions, mutations and getters inside modules are still registered under the global namespace - this allows multiple modules to react to the same mutation/action type.
If you want your modules to be more self-contained or reusable, you can mark it as namespaced withnamespaced: true
Let's see Module Registration as mentioned by Chris Fritz(Vue core member) in a VueConf.
š© Firstly, let's add a index.js
file in store/modules/
# This is our store structure with modules
āāā index.html
āāā main.js
āāā components
āāā store
āāā index.js # where we assemble modules and export the store
āāā modules
āāā index.js # this is the js file that solves the problem
āāā auth.js
āāā posts.js
āāā comments.js
š© Then let's modify this index.js
in store/modules/index.js
import camelCase from 'lodash/camelCase'
// Storing in variable a context with all files in this folder
// ending with `.js`.
const requireModule = require.context('.', false, /\.js$/)
const modules = {}
requireModule.keys().forEach(fileName => {
if (fileName === './index.js') return
// filter fullstops and extension
// and return a camel-case name for the file
const moduleName = camelCase(
fileName.replace(/(\.\/|\.js)/g, '')
)
// create a dynamic object with all modules
modules[moduleName] = {
// add namespace here
namespaced: true,
...requireModule(fileName).default
// if you have exported the object with name in the module `js` file
// e.g., export const name = {};
// uncomment this line and comment the above
// ...requireModule(fileName)[moduleName]
}
})
export default modules
š© Let's delete namespacing from every module js file.
// export const name = { if you want to export an object with name
export default {
// namespaced: true, delete this line
state: {},
getters: {},
mutations: {},
actions: {}
}
š© Finally the code from above, where we had to import all the modules can change to:
index.js
in store/
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules
})
I think we have done an ''automated'' system that includes every file in modules folder. A smarter and cleaner code.
Until next time...Happy coding!
Posted on July 30, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.