Prior to the start

This article is just my summary and understanding of module learning and some opinions to avoid pits, which may not be used in your project. Even if you want to use it, you are advised to refer to the official article for comparison. In addition, Module is a modular management scheme based on VUex, i.e. store state, so this is a personal summary for reference only for students who have experience in using store. If you still don’t know store, you have to hurry up! Or you can refer to The teacher of “Vuex vernacular course sixth lecture: Vuex administrator Module (Actual combat)”

Local state of a module

Mutation and getter inside the module, the first argument received is the module’s local state object:

const moduleA = {

    state: { count:10 },

    getters:{

        filterCount(state){

            return state.count * 2/ / 20;

        }

    },

    mutations:{

        add(state){

            state.count * 2/ / 20;

        }

    },

}

Copy the code

Actions are exposed through context.state:

actions:{

    incrementIfOddOnRootSum(context){

        context.state.count / / 10

    }

}

Copy the code

The state of global access within the module

Action can obtain the state of the root node from rootState:

actions:{

    incrementIfOddOnRootSum( { state, rootState } ){

        rootState.xx // xx of the root node

    }

}

Copy the code

The getter accepts the root node state as exposed by a third argument:

getters:{

    sumWithRootCount(state, getters, rootState){

        //state is the internal state of the module

        // getters other getters inside the module

        // rootState is the global state

    }

}

Copy the code

The concept of namespaces

Getters, actions, and mutations are registered in the global namespace by default if the module does not use namespaces.

store:{

    state:{

        count:18.

    },

    mutations:{

        setCount(state){

            state.count / 2;

            console.log(state.count) / / 9

        }

    },

    modules:{

        a:moduleA

    }

}

moduleA:{

    state:{

        count:10.

    },

    mutations:{

        setCount(state){

            state.count * 2;

            console.log(state.count)/ / 20

        }

    }

}

Copy the code

When submitting the moduleA mutation:

this.$store.commit('setCount');

// Guess what?

This is because the getters, actions, and mutations inside the module described earlier are registered in the global global namespace.

// So in the above example there were two setCount mutations in the global namespace, and they were both triggered.

Copy the code

Enabling the namespace

To make getters, mutation, and actions within a module only apply to the current local module, you can add a namespaced property to the module:

modules:{

    moduleA:{

        namespaced:true,

        state:{.}, //state still applies only to the current module

        getter:{

            isAdmin(){.}

        },

        mutations:{

            login(){.}

        },

        actions:{

            getToken(){.}

        }

    }

}

Copy the code

All getters, actions, and mutations of a module that has namespace enabled are automatically named according to the path in which the module was registered.

store.getters['moduleA/isAdmin']; // The getter inside the namespace module

store.dispatch('moduleA/getToken'); // Action inside the namespace module

store.commit('moduleA/login'); // mutation inside the namespace module

Copy the code

Nesting of namespace modules

Nested modules can also be nested within modules.

modules:{

    moduleA:{

        state:{.},

        mutations:{.},

// Nested modules

        modules:{

            mypage:{

                state:{.},

                getters:{

Profile (state){}// Since the nested module does not have its own namespace, it automatically inherits its parent namespace, so it can trigger the getter: store.getters['moduleA/profile'];

                }

            },

// Further nested namespaces

            posts:{

Namespaced :true,// enable the namespace

                state:{.},

                getters:{

                    popular(){.}// all getters, actions, and mutations are automatically named based on the path of the module -> store.getters['moduleA/posts/popular']

                }

            }

        }

    }

}

Copy the code

Problems with nested modules inheriting namespaces

Following the example of inherited namespaces above:

modules:{

    moduleA:{

        state:{.},

        mutations:{.},

// Nested modules

        modules:{

            mypage:{

                state:{.},

                getters:{

                    profile(){.}

                }

            }

        }

    }

}

Copy the code

Now if I want to trigger the getter for the profile I can do this:

store.getters['moduleA/profile'];

Copy the code

Since mypage doesn’t have its own namespace, it inherits its parent namespace, so this firing looks fine.

The question is ⚠️

If the parent namespace also has a getter named profile:

modules:{

    moduleA:{

        state:{.},

        getters:{

            profile(state){.}

        }

        mutations:{.},

// Nested modules

        modules:{

            mypage:{

                state:{.},

                getters:{

                    profile(){.}

                }

            }

        }

    }

}

Copy the code

At this point, if you execute:

store.getters['moduleA/profile'];

Copy the code

What would be the result? You can try it yourself and deepen your impression.

Some interactions between namespaced modules and global namespace modules

Get or modify global state:

If you want to use the global state and getter, rootState and rootGetters are passed to the getter as the third and fourth arguments, and the action is passed to the context object’s properties.

modules: {

      foo: {

        namespaced: true.

        getters:{

            someGetter(state, getters, rootState, rootGettrers){

                // state is the state inside the current module

                // getters is the getters inside the current module

                // rootState is the global state

                // rootGettrers is global gettrers

            }

        },

        actions:{

            someAction( { getters, rootGetters}){

                // getters: getters inside the current module,

                // rootGettrers is global gettrers

            }

        }

      }

 }

Copy the code

To distribute action or commit mutation in the global namespace, pass {root: true} as the third argument to Dispatch or COMMIT:

action:{

    someAction( { dispatch, commit}){

        dispatch('someOtherAction');// Distribute the action named someOtherAction in the current module

        dispatch('someOtherAction'.null, { root: true })// Distribute the action with the global name someOtherAction

        commit('someMutation'// Submit the mutation named someMutation in the current module

        commit('someMutation'.null, { root: true }) // Submit mutation with the global name someMutation

    }

}

Copy the code

Yes, global access requires only the rootState and rootGetters parameters, and distribution of action or mutation requires only {root: true} as the third parameter.

Register actions within a module globally:

If the business needs to register a global action in a module with a namespace, you can add root: true and put the action definition in a function handler. Such as:

{

    actions: {

        someOtherAction ({dispatch}) {

            dispatch('someAction')

        }

    },

    modules: {

        foo: {

        namespaced: true.

        actions: {

            someAction: {

                  root: true.

handler (namespacedContext, payload) { ... } / / - >'someAction'

                }

            }

        }

    }

}

Copy the code

Use modules with namespaces in components

There are two official solutions, here I use the namespace helper function writing method, the other method is interested in students can refer to

This example has been given very succinct and intuitive by the official, so let’s just look at it:

import { createNamespacedHelpers } from 'vuex'



const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')



export default {

  computed: {

    // Find in the context of 'some/nested/module'

. mapState({

      astate= > state.a,

      bstate= > state.b

    })

  },

  methods: {

    // Find in the context of 'some/nested/module'

. mapActions([

      'foo'.

      'bar'

    ])

  }

}

Copy the code

I have a question about this example: if mapState and mapActions are based on the ‘some/nested/module’ context, what if I need modules in this component that use other namespaces? Some of you might say,

    const { mapState, mapActions } = createNamespacedHelpers('otherSome/nested/module')

Copy the code

Wouldn’t it be nice to define another context? But both contexts return the same mapState and mapActions, so when I use mapActions, how do you know which context I’m looking in? … Later, I thought about whether this question is established? Because I think a module store should always work for a functional component. But there is no guarantee that there will not be extreme cases, and if there is such a need, how to achieve it? Experienced students can teach me.

Dynamically register the namespace module

If a business requirement requires us to register a module dynamically, we can register the module using the store.registerModule method:

// Register module 'myModule'

store.registerModule('myModule', {

  // ...

})

// Register nested modules' myModule '

store.registerModule(['nested'.'myModule'] and {

  // ...

})

Copy the code

Dynamic registration requires that your Store is already created by you.

Can be used after store. State. MyModule and store state. Nested. MyModule access module.

Uninstalling dynamic Modules

You can then use Store. unregisterModule(moduleName) to dynamically unload modules when they are not needed to ensure performance

Note: You cannot use this method to uninstall static modules (that is, modules declared when creating a store)

Module reuse

Create multiple stores that share the same module. 2. Register the same module multiple times in the same store.

moduleA.js

const moduleA = {

    state:{

        count:10

},

    mutations:{

        changeCount(state){

            state.count = 20;

        }

    }

}

export default moduleA;

Copy the code

store.js

const store = new Vuex.Store({

state:{... }

mutations:{... },

    modules:{

        a:moduleA,

        b:moduleA,

        c:moduleA

    }

})

Copy the code

A, B, and C in the Modules object refer to moduleA. Let’s create three more components and reference each instance of module A, b, and C:

test1.vue

<template>

    <div>

        {{count}}

    </div>

</template>

<script>

    import { createNamespacedHelpers } from 'vuex'

    const { mapState } = createNamespacedHelpers('a')

    export default {

        computed: {

. mapState({

                name:state= > state.count

            })

        }

    }

</script>

Copy the code

test2.vue

<template>

    <div>

        {{count}}

    </div>

</template>

<script>

    import { createNamespacedHelpers } from 'vuex'

    const { mapState } = createNamespacedHelpers('b')

    export default {

        computed: {

. mapState({

                name:state= > state.count

            })

        }

    }

</script>

Copy the code

test3.vue

<template>

    <div>

        {{count}}

    </div>

</template>

<script>

    import { createNamespacedHelpers } from 'vuex'

    const { mapState } = createNamespacedHelpers('c')

    export default {

            computed: {

. mapState({

                name:state= > state.count

            })

        }

    }

</script>

Copy the code

The count of the three components is equal to 10, because ModuleA, B and C all reference moduleA. If we submit the moduleA mutation in the test1 component:

test1.vue

<template>

    <div>

        {{count}}

         <input type="button" value="click" @click="changeCount">



    </div>

</template>

<script>

    import { createNamespacedHelpers } from 'vuex'

    const { mapState,mapMutations } = createNamespacedHelpers('a')

    export default {

        methods: {

. mapMutations([changeCount])

        }

        computed: {

. mapState({

                name:state= > state.count

            })

        }

    }

</script>

Copy the code

Whenever we submit changeCount, count in test1, test2, test3 will be changed to 20; The reason:

When a module is defined, the module can be used to create multiple instances, and if the module remains a pure object, all instances will share references to the same data object! This is the problem of data contamination between modules.

Solve the problem of mutual pollution caused by module reuse

To resolve cross-contamination we can use a function declaration to return the module’s state:

const MyReusableModule = {

  state () {

    return {

      count: 10

    }

  },

  // mutation, action and getters, etc...

}

Copy the code

By declaring a function for the initial data object for state, and each time a new instance is created, we can call the state function to return a new copy of the original data object.

This reference to data in Vue components basically means that state is returned as a function declaration, so that no matter how many times the module is instantiated, the state inside the module will be returned as a new function each time it is instantiated.

The last

Some advice for some students: taking notes and summarizing things must require you to study them and then understand them. It’s not about putting things from other people’s documents into your notes. What’s the point? Cheat click sand sculpture net friend we did not evaluate, and somebody else’s document thing is always the latest, but also have continued to update. Please don’t waste everyone’s time. Purify the learning environment from me!

Of course, a summary will always include examples from the original document.