Vuex auxiliary function -mapState
Vuex provides four commonly used helper functions
- mapState
- mapGetters
- mapActions
- mapMutations
mapState
mapState(namespace? : string, map: Array<string> | Object<string | function>): Object
- Create computed properties for the component to return the state in the Vuex Store
- The first argument is optional and can be a namespace string, and the member of the second argument in object form can be a function.
Computed: mapState({// Arrow function makes code more concise count: State => state.count, // Pass string argument 'count' equal to 'state => state.count' countAlias: CountPlusLocalState (state) {return state.count + this.localcount}})Copy the code
Take a look at the source (vuex\ SRC \helpers.js) :
export const mapState = normalizeNamespace((namespace, states) => { const res = {} normalizeMap(states).forEach(({ key, val }) => { res[key] = function mappedState () { let state = this.$store.state let getters = this.$store.getters if (namespace) { const module = getModuleByNamespace(this.$store, 'mapState', namespace) if (! module) { return } state = module.context.state getters = module.context.getters } return typeof val === 'function' ? val.call(this, state, getters) : state[val] } // mark vuex getter for devtools res[key].vuex = true }) return res }) function normalizeNamespace (fn) { return (namespace, map) => { if (typeof namespace ! == 'string') { map = namespace namespace = '' } else if (namespace.charAt(namespace.length - 1) ! == '/') { namespace += '/' } return fn(namespace, map) } } function normalizeMap (map) { if (! isValidMap(map)) { return [] } return Array.isArray(map) ? map.map(key => ({ key, val: key })) : Object.keys(map).map(key => ({ key, val: map[key] })) }Copy the code
MapState is a function returned by normalizeNamespace, which receives parameters: namespace,map. Namespace is a namespace, and map is a specific object. Once normalizeNamespace is called, the map is passed in as state, and then normalizeMap is called to change the map to an array in the format {key,val:key}. Once the build is complete. Execute the loop, and then store the key and val as mappedState as value into the RES
mappedState
res[key] = function mappedState () { let state = this.$store.state let getters = this.$store.getters if (namespace) { const module = getModuleByNamespace(this.$store, 'mapState', namespace) if (! module) { return } state = module.context.state getters = module.context.getters } return typeof val === 'function' ? val.call(this, state, getters) : state[val] }Copy the code
Get $store.state and $store.getters first
If the namespace is
Then, according to the namespace name, the module is obtained, and the corresponding state and getters of the module are obtained. We then execute the function, passing in state and getters, and return state[val] if the second argument to our written mapState is a function.
Example:
/ / attribute-based access mapState ({searchInput: state = > state. YourModuleName. SearchInput,}) / / using the namespace access... mapState('yourModuleName',[ 'searchInput', ])Copy the code
mapGetters
mapGetters(namespace? : string, map: Array<string> | Object<string>): Object
Create computed properties for the component to return the return value of the getter. The first argument is optional and can be a namespace string
Official example:
// map for Array computed: {// Mix getters into computed objects using the object expansion operator... mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ] } // map is an Object... MapGetters ({/ / the ` enclosing doneCount ` mapping for ` enclosing $store. The getters. DoneTodosCount ` doneCount: 'doneTodosCount})Copy the code
Look at the source code implementation
export const mapGetters = normalizeNamespace((namespace, getters) => { const res = {} normalizeMap(getters).forEach(({ key, val }) => { // The namespace has been mutated by normalizeNamespace val = namespace + val res[key] = function mappedGetter () { if (namespace && ! getModuleByNamespace(this.$store, 'mapGetters', namespace)) { return } return this.$store.getters[val] } // mark vuex getter for devtools res[key].vuex = true }) return res })Copy the code
Unlike mapState, mapGetters uses this.$store.getters to get the value
mapMutations
Example:
methods: { ... Apply mutations ([' increments ', // map 'this.increment()' to 'this.store.com MIT (' increments ')' 'incrementBy' // Map 'this.incrementBy(amount)' to 'this.incrementBy(amount)'),... mapMutations({ account: (commit, account) => { commit("account", account) }, }), ... MapMutations ({add: 'increment' // map 'this.add()' to 'this.store.mit ('increment')'})}Copy the code
mapMutations(namespace? : string, map: Array<string> | Object<string | function>): Object
- Create the component method to commit mutation
- The first argument is optional and can be a namespace string
- The member of the second argument in object form can be a function. function(commit: function, … args: any[])
export const mapMutations = normalizeNamespace((namespace, mutations) => { const res = {} normalizeMap(mutations).forEach(({ key, val }) => { res[key] = function mappedMutation (... args) { // Get the commit method from store let commit = this.$store.commit if (namespace) { const module = getModuleByNamespace(this.$store, 'mapMutations', namespace) if (! module) { return } commit = module.context.commit } return typeof val === 'function' ? val.apply(this, [commit].concat(args)) : commit.apply(this.$store, [val].concat(args)) } }) return res })Copy the code
- First of all, get all the
mutaions
Access to the{key,val:key}
Something like this, you get an array of formats, and you loop through it - Then from
this.$store
Access to thecommit
This method, if it’s a namespacemodule
“, then it will passgetModuleByNamespace
Get the correspondingmodule
- Finally, execute the corresponding
store
Within thecommit
- if
val
isfunction
(example second case), two values are passed in, onecommit
, aparameter
So that’s why it’s available. Rightcommit
At the same time will own the payloadpayload
Incoming cause - If it is not
function
So it’s going to becommit.apply(this.$store, [val].concat(args))
And then commit the changestate
mapActions
Example:
// Array ... MapActions (['increment', // Map 'this.increment()' to 'this.$store.dispatch('increment')' // 'mapActions' also supports payloads: 'incrementBy' // map 'this.incrementBy(amount)' to 'this.$store.dispatch('incrementBy', amount)']), // Object... MapActions ({add: 'increment' // map 'this.add()' to 'this.$store.dispatch('increment')'})Copy the code
Look at the source code implementation:
export const mapActions = normalizeNamespace((namespace, actions) => { const res = {} normalizeMap(actions).forEach(({ key, val }) => { res[key] = function mappedAction (... args) { // get dispatch function from store let dispatch = this.$store.dispatch if (namespace) { const module = getModuleByNamespace(this.$store, 'mapActions', namespace) if (! module) { return } dispatch = module.context.dispatch } return typeof val === 'function' ? val.apply(this, [dispatch].concat(args)) : dispatch.apply(this.$store, [val].concat(args)) } }) return res })Copy the code
- We know that
actions
Is for distributingmutations
So you definitely need onedispatch
Can come fromThe rootIt can also beThe child module - Judge here with
mutation
It’s the same thing. It’s divided intofun
And other types as handled