current position:Home>Correctly use the auxiliary functions in vuex in vue3

Correctly use the auxiliary functions in vuex in vue3

2021-08-27 09:42:36 pfzzz

Preface

In actual development , We often use vuex To manage data , With more and more data , We gradually began to use some grammar sugar to help us develop . namely vuex Medium mapState、mapGetters、mapMutations、mapActions Such auxiliary functions are often used by us .

Use of auxiliary functions

stay vue2 We can pass options API stay computed To use mapState,

computed: mapsState(['name','age'])
 Copy code 

stay vue3 It is mainly used in setup To operate , Generally used vuex This is how the data in , adopt useStore Use this hook to get

import { useStore } from 'vuex'
import { computed } from 'vue'

setup() {
  const store = useStore()
  const name = computed(() => store.state.name)
  const age = computed(() => store.state.age)
  return {
    name, age
  }
},
 Copy code 

The disadvantage is that if there are too many data , Then writing is particularly troublesome , So we thought of auxiliary functions mapState To solve . But what? ,vuex There are no official examples of how to setup To use auxiliary functions mapState. So I tried to vue2 In the form of :

setup() {
  const stateStore = mapState(['name', 'age'])
  return {
    ...stateStore
  }
},
 Copy code 

But the result displayed in the browser is like this :

mapState.png

Why does it return a function ?

Why is it setup Use in mapState Will return the function ?

I tried to have a look mapState Source code , Discovery is through this.$store Come and get it store The value of the

However, in setup You can't get this Of

mapState Source code .png

Other auxiliary functions (mapGetters、mapMutations、mapActions) Similarly, they are handled in a similar way . So through the above source code , We know : An auxiliary function returns an object , and key Is string , val Namely function , Be similar to :

computed:{
    ...mapState(['name','age'])
}
//  Convert to :
{ 
    name: function(){},
    age:function(){}
}
 Copy code 

So you can see why a function is returned in the above code .

Encapsulates a useState function

After understanding its principle , We knew it was computed Can be used in mapState, Because computed It's a function in itself , It takes a function as an argument . We also know that the auxiliary function is It is parsed into an object , The property value in the object is a function .

So can we try to combine these two to encapsulate one hooks To use ?

import { useStore, mapState } from 'vuex'
import { computed } from 'vue'

const useState = function(mapper) {
    // mapper: Array | Object
    const store = useStore()
    
    // Use auxiliary functions to parse into an object 
    const storeStateFns = mapState(mapper)
    const storeState = {}
    
    // adopt Object.keys Get all the objects key value , Traverse , Take out the corresponding value value , That's the function 
    Object.keys(storeStateFns).forEach(item => {
        //  We know that the interior of the auxiliary function is through this.$store To achieve 
        // setup There is no this,  So pass bind To change this The direction of 
        const fn = storeStateFns[item].bind({$store, store})
        // Get the function , Parameters as calculated properties , Finally, stay in an object 
        storeState[item] = computed(fn)
    })
    
    // storeState It's an object , key Is string , value The value is ref object 
    return storeState
}

export default useState
 Copy code 

Then use it in the component like this :

setup(){
    const stateStore = useState(['name','age']) //  It's OK to use the form of objects 
    return {
        ...stateStore
    }
}
 Copy code 

So you can do it setup Use auxiliary functions in , How happy to have less code again ~

Encapsulates a useMapper function

alike , It's not just mapState, mapGetters It is also packaged according to the same idea , So a little modification . as follows :

// hooks/useMapper.js

import { computed } from 'vue'
import { mapGetters, mapState, useStore } from 'vuex'

const useMapper = (mapper, mapFn) => {
  const store = useStore()

  const storeStateFns = mapFn(mapper)
  const storeState = {}
  Object.keys(storeStateFns).forEach((keyFn) => {
    const fn = storeStateFns[keyFn].bind({ $store: store })
    storeState[keyFn] = computed(fn)
  })

  return storeState
}

export const useState = ( mapper) => {
  return useMapper(mapper, mapState)
}

export const useGetters = (mapper) => {
  return useMapper(mapper, mapGetters)
}
 Copy code 

Then use it like this :

 Example .png

About mapMutations、mapActions There is no need to package , You can think for yourself

Actually, ha , Use mutaiton and actions Is to call a method in , Therefore, it is directly linked to the attribute value of the auxiliary function .

Consideration in the case of modularity

Just encapsulated useMapper Modularity is not considered , At development time , With more and more kinds of data , Use modules Is inevitable , So we need to be right about what just happened useMapper Go ahead Modular edge processing

as follows : We need the help of vuex Provided createNamespacedHelpers Function to get the attributes in the module

import { computed } from 'vue'
import { mapGetters, mapState, useStore, createNamespacedHelpers } from 'vuex'

const useMapper = (mapper, mapFn) => {
  const store = useStore()

  const storeStateFns = mapFn(mapper)
  const storeState = {}
  Object.keys(storeStateFns).forEach((keyFn) => {
    const fn = storeStateFns[keyFn].bind({ $store: store })
    storeState[keyFn] = computed(fn)
  })

  return storeState
}

export const useState = (moduleName, mapper) => {
  let mapperFn = mapState
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapState
  } else {
    mapper = moduleName
  }
  return useMapper(mapper, mapperFn)
}

export const useGetters = (moduleName, mapper) => {
  let mapperFn = mapGetters
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapGetters
  } else {
    mapper = moduleName
  }
  return useMapper(mapper, mapperFn)
}
 Copy code 

Use :

setup() {
  const storeState = useState(['name', 'age', 'six'])
  const storeGetters = useGetters(['counter'])
  const homeState = useState('home', ['homeCounter'])
  return {
    ...storeState,
    ...storeGetters,
    ...homeState
  }
},
 Copy code 

summary

stay vue2 I'm used to using auxiliary functions , But in vuex Not found in the document vue3 How to use auxiliary functions in , Then keep using computed Come and go package store To get the value , With the increase of data , It's also troublesome to use , So it encapsulates such a function to improve development efficiency .

copyright notice
author[pfzzz],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827094232499w.html

Random recommended