Use and principle of Vuex

Keywords: React

1, What is Vuex?

Vuex is a state management mode specially designed for Vuejs applications, similar to Redux in React. It uses centralized storage to manage the status of all components of the application.

  • Official explanation: Vuex is a state management mode specially developed for Vue.js applications. It uses centralized storage to manage the state of all components of the application, and uses corresponding rules to ensure that the state changes in a predictable way.
  • Personal understanding: Vuex is a third-party "warehouse" used for data exchange between components. Components can store the data they want to share in it, and other components can directly fetch what they want.

Vuex principle understanding  

Personal understanding is through   Global blending   For an object, in the beforeCreate declaration cycle function of the object, an attribute $store is added to each component, and the value is the Vuex instance created when using Vuex.

1. Composition of Vuex  

  • state

State is Vuex's data center, that is, state is used to store data.

  • Getters

Getters is similar to the computed of components, so it is convenient to directly generate some data that can be used directly. When the assembled data needs to be used in multiple pages, you can use getters.

  • Mutations

Changes submit the change data, and use the store.commit method to change the state of the state store.

  • Actions

The Action submits the mutation instead of directly changing the status. An Action can contain any asynchronous Action.

  2. How Vuex is used

Install Vuex

Mode 1: npm mode

npm install vuex --save

Introduce Vuex into the application

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)   

Get Vuex state in Vue component  

  Method 1: this.$store.state

By registering the store option in the root instance, the store instance will be injected into all sub components under the root component, and the sub components can be accessed through this.$store

    const Counter = {
        template: `<div>{{ count }}</div>`,
        computed: {
            count () {
                return this.$store.state.count
            }
        }
    }

  Method 2: get mapState auxiliary function (recommended)

When a component needs to obtain multiple states, declaring these states as calculation attributes will be somewhat repetitive and redundant. To solve this problem, we can use the mapState auxiliary function to help us generate calculation properties, so that you can press the key a few times less:

    import { mapState } from "vuex";
    export default {
    // ...
    computed: mapState({
        // Arrow functions make the code simpler
        count: state => state.count,

        // The string parameter 'count' is equivalent to ` state = > state.count`
        countAlias: 'count',

        // In order to use 'this' to get the local state, you must use the regular function
        countPlusLocalState (state) {
            return state.count + this.localCount
        }
    })
}

  When the name of the mapped calculated attribute is the same as the child node name of state, we can also pass a string array to mapState.

    computed: mapState([
        // Map this.count to store.state.count
        'count'
    ])

  Get Getter

Sometimes we need to derive some states from the state in the store, such as filtering and counting the list:

    computed: {
        doneTodosCount () {
            return this.$store.state.todos.filter(todo => todo.done).length
        } 
    }

  Vuex allows us to define "getters" (which can be considered as the calculated attributes of the store) in the store. Just like calculating attributes, the return value of getter will be cached according to its dependency, and will be recalculated only when its dependency value changes.

Mode 1:   Access through properties

    store.getters.doneTodos

  Mode 2:   Access by method

You can also pass parameters to getters by letting getters return a function. It is very useful when you query the array in the store.

   getters: {
     // ...
     getTodoById: (state) => (id) => {
       return state.todos.find(todo => todo.id === id)
     }
   }
    store.getters.getTodoById(2)

Note that when a getter is accessed through a method, it will be called every time, and the result will not be cached.

Mode 3:   mapGetters auxiliary function acquisition (recommended)

    import { mapGetters } from 'vuex'

    export default {
      // ...
      computed: {
      // Use the object expansion operator to mix getter s into the computed object
        ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
        ])
      }
    }

  If you want to give a getter property another name, use the object form:

    mapGetters({
      // Map 'this.doneCount' to 'this. $store.getters.donetodocount'`
      doneCount: 'doneTodosCount'
    })

  Usage of station

As mentioned above, the only way to change the state in Vuex's store is to submit a mutation. The mutation in Vuex is very similar to events: each mutation has a string event type and a callback function (handler). This callback function is where we actually make state changes, and it will accept state as the first parameter.

Replace the Mutation event type with a constant

    // mutation-types.js
    export const SOME_MUTATION = 'SOME_MUTATION'
    // store.js
    import Vuex from 'vuex'
    import { SOME_MUTATION } from './mutation-types'
    
    const store = new Vuex.Store({
      state: { ... },
      mutations: {
        // We can use the ES2015 style calculation attribute naming function to use a constant as the function name
        [SOME_MUTATION] (state) {
          // mutate state
        }
      }
    })

Submit the Mutation in the component

You can use this.$store.commit('xxx ') to submit the mutation in the component, or use the mapMutations auxiliary function to map the methods in the component into a store.commit call (store needs to be injected into the root node).

    import { mapMutations } from 'vuex'

    export default {
      // ...
      methods: {
        ...mapMutations([
          'increment', // Map 'this.increment()' to 'this.$store.commit('increment')`
    
          // `mapMutations ` also supports loads:
          'incrementBy' // Map ` this.incrementBy(amount) ` to ` this.$store.commit('incrementBy', amount)`
        ]),
        ...mapMutations({
          add: 'increment' // Map 'this.add()' to 'this.$store.commit('increment')`
        })
      }
    }

  Action usage

The Action function accepts a context object with the same methods and properties as the store instance, so you can call context.commit to submit a mutation, or get the state and getters through context.state and context.getters. When we introduce Modules later, you will know why the context object is not the store instance itself.

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        }
      }
    })

  Distribute Action

    // Distribute as load
    store.dispatch('incrementAsync', {
      amount: 10
    })
    
    // Distribute as objects
    store.dispatch({
      type: 'incrementAsync',
      amount: 10
    })

Distribute actions in components

You can use this.$store.dispatch('xxx ') to distribute actions in the component, or use the mapActions auxiliary function to map the component's methods to store.dispatch calls (store needs to be injected into the root node first)

    import { mapActions } from 'vuex'

    export default {
      // ...
      methods: {
        ...mapActions([
          'increment', // Map 'this.increment()' to 'this.$store.dispatch('increment')`
    
          // `mapActions ` also supports loads:
          'incrementBy' // Map ` this.incrementBy(amount) ` to ` this.$store.dispatch('incrementBy', amount)`
        ]),
        ...mapActions({
          add: 'increment' // Map 'this.add()' to 'this.$store.dispatch('increment')`
        })
      }
    }

 

Posted by trg on Tue, 21 Sep 2021 20:59:52 -0700