Vuex auxiliary function -mapState

Vuex provides four commonly used helper functions

  1. mapState
  2. mapGetters
  3. mapActions
  4. mapMutations

mapState

mapState(namespace? : string, map: Array<string> | Object<string | function>): Object

  1. Create computed properties for the component to return the state in the Vuex Store
  2. 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
  1. The first argument is optional and can be a namespace string
  2. 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
  1. First of all, get all themutaionsAccess to the{key,val:key}Something like this, you get an array of formats, and you loop through it
  2. Then fromthis.$storeAccess to thecommitThis method, if it’s a namespacemodule“, then it will passgetModuleByNamespaceGet the correspondingmodule
  3. Finally, execute the correspondingstoreWithin thecommit
  • ifvalisfunction(example second case), two values are passed in, onecommit, aparameterSo that’s why it’s available. RightcommitAt the same time will own the payloadpayloadIncoming cause
  • If it is notfunctionSo 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
  1. We know thatactionsIs for distributingmutationsSo you definitely need onedispatchCan come fromThe rootIt can also beThe child module
  2. Judge here withmutationIt’s the same thing. It’s divided intofunAnd other types as handled