How do I break up my vuex file?
Asked Answered
E

7

26

I have a vuex file with a growing mass of mutators, but I'm not sure of the correct way of splitting it out into different files.

Because I have:

const store = new Vuex.Store({ vuex stuff }) and then below that my main Vue app declaration: const app = new Vue({ stuff })

I'm happy working with Vue components and have lots of those already, but this is stuff at the top level of the app and I'm not sure how to break it apart. Any advice appreciated.

Earshot answered 12/11, 2016 at 14:55 Comment(0)
S
45

For those who would like to break up the Vuex file without creating a more complex modular application structure, I think it is also possible to simply break the actions, mutations and getters into separate files like this:

└── src
     ├── assets
     ├── components
     └── store
           ├── store.js
           ├── actions.js
           ├── mutations.js
           └── getters.js

store.js

import Vuex from 'vuex';
import Vue from 'vue';

import actions from './actions';
import getters from './getters';
import mutations from './mutations';

Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    someObj: {},
  },
  actions,
  getters,
  mutations,
});

actions.js

const actionOne = (context) => {
  ...
  context.commit('PROP1_UPDATED', payload);
};

const actionTwo = (context) => {
  ...
  context.commit('PROP2_UPDATED', payload);
};

export default {
  actionOne,
  actionTwo,
};

mutations.js

const PROP1_UPDATED = (state, payload) => {
  state.someObj.prop1 = payload;
};

const PROP2_UPDATED = (state, payload) => {
  state.someObj.prop2 = payload;
};

export default {
  PROP1_UPDATED,
  PROP2_UPDATED,
};

getters.js

const prop1 = state => state.someObj.prop1;
const prop2 = state => state.someObj.prop2;

export default {
  prop1,
  prop2,
};

...then you are able to do stuff from within your components as you please using the usual this.$store.dispatch('actionOne') ...

Sparhawk answered 12/5, 2018 at 12:9 Comment(12)
This results in "getters should be function but "getters.default" in module "modulename" is {}."Mesolithic
In current version you should not use the keyword "default" at the exports!!Mesolithic
@Mesolithic - this pattern of getters is working fine at my end. Could you share a code example perhaps so I could take a look? Happy to edit if required.Sparhawk
When I changed my export to export { … } it worked for me! Removed the default keyword.Puerperium
@Puerperium interesting that you found that too. Maybe we have a slightly different project set up... or maybe Roel is right and it's a version thing (although that feels less likely). either way, glad you got it working anyway! :)Sparhawk
I think it is because I have an index.js for each store module. I noticed that exports the entire module.Puerperium
hmmm... I gave the example using the global store but I also have modular stores using the same pattern and and index.js for each one. i still use the export default { } syntax throughout. I have each of the modular stores namespaced - perhaps that it something to do with it?Sparhawk
...each module's index.js ends thus: export default { namespaced: true, state, actions, getters, mutations, };Sparhawk
interesting. I posted an answer with my setup that works. Using es6 - js Standard style - Quasar Framework v1 beta. Anyway, +1 from me as you helped me with my project! Cheers!Puerperium
You're welcome - glad I could help! Ah, maybe you had to remove the default part because you use the import * as getters from ... syntax, whereas I just import getters from ...?Sparhawk
@Sparhawk possibly. Js is fun, eh?Puerperium
you might need to set namespaced: true, as wellAide
H
32

This is another option for splitting your store and have diferent modules, this is already tested.

structure

└── src
    ├── assets
    ├── components
    └── store
       └─ modules
          └─ module1
              ├── state.js
              ├── actions.js
              ├── mutations.js
              ├── getters.js
              └── index.js
         └─ module2
              ├── state.js
              ├── actions.js
              ├── mutations.js
              ├── getters.js
              └── index.js
   └─ index.js

store/index.js


import Vuex from "vuex";
import thisismodule1 from "./modules/module1";
import thisismodule2 from "./modules/module2";

const createStore = () => {
  return new Vuex.Store({
    modules: {
      module1: thisismodule1,
      module2: thisismodule2

    }
  });
};

export default createStore;

store/modules/module1/index.js

import actions from './actions';
import getters from './getters';
import mutations from './mutations';
import state from './state';


export default {
  state,
  actions,
  mutations,
  getters
}

store/modules/module2/index.js

import actions from './actions';
import getters from './getters';
import mutations from './mutations';
import state from './state';


export default {
  state,
  actions,
  mutations,
  getters
}

Tipp: Don't forget to import your store to your main.js

Documentation: https://vuex.vuejs.org/en/modules.html

Homeopathist answered 13/3, 2020 at 9:50 Comment(4)
I doubt that this helps, or even works at all. To convince be otherwise please explain how this works and why it is supposed to solve the problem.Affray
It does works, it is tested. This is divided into diferent modulesHomeopathist
The OP doesn't mention a modular application structure of the application but perhaps useful for other people with more complex use cases than the OP.Sparhawk
Since @Puerperium already put a good modular example, perhaps it would have been better and tidier for future readers just to add your store/index.js to that existing response. Or have you added something else that I've missed? :)Sparhawk
K
15

You can break them into different modules. That way you can keep all related mutations, getters, state and actions in separate files. The documentation explains it better than I can: https://vuex.vuejs.org/en/modules.html

Kilburn answered 13/11, 2016 at 0:11 Comment(3)
As expected, my attempts at doing this have resulted in store is not defined errors on the very first store.commit in the first component.Earshot
That's not enough detail to give any help.Kilburn
Here is example code on how to break it github.com/vuejs/vuex/tree/dev/examples/shopping-cart/storeBuckish
P
7

In addition to @bigsee's fine answer, if using an index.js file to export the module:

└── src
    ├── assets
    ├── components
    └── store
          └─ mymodule
              ├── state.js
              ├── actions.js
              ├── mutations.js
              ├── getters.js
              └── index.js

index.js

import state from './state'
import * as getters from './getters'
import * as mutations from './mutations'
import * as actions from './actions'

export default {

  state,
  getters,
  mutations,
  actions
}

getters.js

const getData = state => state.data

export {
  getData
}

Similar with actions, mutations and state files.

Puerperium answered 23/3, 2019 at 3:15 Comment(0)
C
0

You can use this structure with dynamically load store modules.

src
└─ store
   └─ modules
      └─ [module-name].js
      └─ ...
   └─ index.js // <- your store main file

and in index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// Load store modules dynamically.
const requireContext = require.context('./modules', false, /.*\.js$/)

const modules = requireContext.keys()
  .map(file =>
    [file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)]
  )
  .reduce((modules, [name, module]) => {
    if (module.namespaced === undefined) {
      module.namespaced = true
    }

    return { ...modules, [name]: module }
  }, {})

export default new Vuex.Store({
  modules
})

after that, just put your module [name].js in modules folder, eg:
auth.js:

// state
export const state = {}

// getters
export const getters = {}

// mutations
export const mutations = {}

// actions
export const actions = {}

to access your actions/getters.. You must write:

export default {
  computed: {
    ...mapGetters({
      method_1: '[module-name]/method_1',
      method_2: '[module-name]/method_2',
    }),
    method_with_arg(){
      return this.$store.getters['[module-name]/method_with_arg'](this.n)
    }
  },
...

You can find demo here (laravel-vue-spa) by Cretu Eusebiu.
Thank you.

Convenance answered 15/6, 2020 at 16:17 Comment(0)
D
0

i have this structure:

└── store
          └─ module1
              ├── actions.js
              ├── mutations.js
              ├── getters.js
              └── index.js
   index.js 

and you can copy this example code : index.js from module1

    import actions from "./actions";
    import getters from "./getters";
    import mutations from "./mutations";
    
    import { state } from "./state";

    export default {
     state: () => state,
     actions,
     mutations,
     getters,
   };

state:

export let state = {
  themes: [],
};

getters:

const themesList = (state) => {
  return state.themes;
};

actions:

const getThemesList = async ({ commit }) => {
  
  commit(types.GET_THEMES, [values]);
};

mutations:

const GET_THEMES = (state, themes) => {
  state.themes = themes;
};

and in the main index.js in store put this

const createStore = () => {
  return new Vuex.Store({
    modules: {
      module1: module1,
    },
  });
};

export default createStore;
Dodi answered 17/9, 2020 at 21:11 Comment(0)
J
0

For more nested moudles, you can export 'modules' in sub-module.

How to expose moudles in sub module?

import Vuex from 'vuex';
import Vue from 'vue';
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
import moudles from './moudles';

Vue.use(Vuex);

export const store = new Vuex.Store({
  state: {
    someObj: {},
  },
  actions,
  getters,
  mutations,
  moudles,
});
└── src
    ├── assets
    ├── components
    └── store
       └─ modules
          └─ module1
              ├── state.js
              ├── actions.js
              ├── mutations.js
              ├── getters.js
              └── index.js
              ├── modules
                 |____moudleA (state.js.....)
                 |____moudleB (state.js.....)         
                  
         └─ module2
              ├── state.js
              ├── actions.js
              ├── mutations.js
              ├── getters.js
              └── index.js
   └─ index.js

More details pls refer to https://vuex.vuejs.org/guide/modules.html

Jedidiah answered 20/4, 2021 at 8:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.