Hey in this Post We will see how can we add multiple Vuejs modules at once.
We all needed to import modules each time we create one on our modules folder like this (is from a real world project).
store/index.js
import Vue from "vue";
import Vuex from "vuex";
import auth from "./modules/auth";
import rows from "./modules/rows";
import rooms from "./modules/rooms";
import students from "./modules/students";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
auth,
rows,
rooms,
students
}
});
Like you see in the example above we have a 10 extra lines in our code. 5 lines to import the modules and 5 others to declare them on modules object.
Let's see now how can we reduce this 10 lines to 1 line So to do that we need to create an index.js
file on modules folder that can listen to all the .js
files inside modules folder and import them one by one.
modules/index.js
import camelCase from "lodash/camelCase";
const requireModule = require.context(".", false, /\.js$/); //extract js files inside modules folder
const modules = {};
requireModule.keys().forEach(fileName => {
if (fileName === "./index.js") return; //reject the index.js file
const moduleName = camelCase(fileName.replace(/(\.\/|\.js)/g, "")); //
modules[moduleName] = requireModule(fileName).default;
});
export default modules;
modules/auth.js
import auth from "../api/auth";
const state = {
isLoggedIn: !!localStorage.getItem("token"),
};
const getters = {
isLoggedIn: state => {
return state.isLoggedIn;
}
};
const actions = {
async loginUser({ commit }, data) {
return await auth.login(data, data => {
localStorage.setItem("token", data.access_token);
commit("loginUser");
});
},
async registerUser({ commit }, data) {
await auth.register(data, data => {
localStorage.setItem("token", data.access_token);
commit("loginUser");
return data;
});
},
async logoutUser({ commit }) {
return await auth.logout(data => {
localStorage.removeItem("token");
commit("logoutUser");
});
}
};
const mutations = {
loginUser: state => {
state.isLoggedIn = true;
},
logoutUser: state => {
state.isLoggedIn = false;
}
};
export default {
state,
actions,
mutations,
getters
};
Now we go back to our store/index.js
and just import "./modules"
equivalent to "./modules/index.js"
store/index.js
import Vue from "vue";
import Vuex from "vuex";
import modules from "./modules";
Vue.use(Vuex);
export default new Vuex.Store({
modules // Equivalent to => modules : modules(imported)
});
You can see now how our store/index.js is clean.
For more informations check chris vfritz repo.
Top comments (12)
This is good, but how you load store files from folders? Lets say you have
chats
index.js // module store file
users
index.js // module store file
How we can import these modules store files dynamically? I mean we may not know the folder (chats, users) names.
any idea how this can be done please
I have done a nice set up for laravel vue module which you can see and also made a tutorial
github.com/hkmsadek/laravel-vue-mo...
youtube.com/watch?v=nW0eGVb0W-A&t=2s
Thank you so much, you do a good trick really
Thanks :)
Hi everyone, anyone looking for an extended solution with the tutorial please look at this with gihub code
github.com/hkmsadek/laravel-vue-mo...
Watch the tutorial from here.
https://www.youtube.com/watch?v=nW0eGVb0W-A&t=2s
Thank you @mohamed for such a nice idea.
Hi, thank you for the post.
I have a question if you can help me.
I have the following folder structure in my project
project
|
-store
|
|-constants.js
|-modules
|
|-someModule
|-otherModule
|-index.js (just as in your post)
This is a sample from my constants file
//Actions
export const USER_SET = 'user/SET'
export const USER_GET_ROLES = 'user/GET_ROLES'
//Mutations
export const USER_SET_BY_KEY = 'user/SET_BY_KEY'
export const USER_SET_ROLES = 'user/SET_ROLES'
And in my modules I use the constant as name for the actions, mutations, getters, like in this sample
const actions =
{
[constants.USER_SET]: ({commit}, user) =>
{
let response = {'data': user, 'key': 'user' }
commit(constants.USER_SET_BY_KEY, response)
},
}
The idea is that when I use in components, i use the constants file name too, this way I can change the name in one place
Like in this
...mapActions({
getRoles: constants.USER_GET_ROLES,
The thing is, even when the module are dinamically loaded by the index in the modules folder, Vuex doesn't recognize the actions, mutations, getters
I print the modules object in the index and i see that it has this properties empty
{
"customer": {
"state": {
"customers": null,
"contacts": null
},
"actions": {},
"mutations": {},
"getters": {}
},
.
.
.
.
}
If I go back to import every module manually and put then in the vuex individually, then vuex recognize the actions, mutations, getters
So thank you in advance if can you please point me in the right direction
p.s Sorry for my bad english, it's not my native language
Nevermind, It was a problem with the way I was telling vuex to use modules but thank you anyway
Glad you figured it out !
Ohh that what I wanted, Thanks you soo much.
I created block builder, combined your solution + v-bind:is and it is great, I just create new file in modules and all other is done, I dont care for anything :D
Is it possible to lazy load the VueX modules?
This is cool Mohammed, thank you.