The basic idea behind Vuex is to extract the shared state of components and manage it in a global singleton mode. In this mode, our tree of components forms a huge “view” where any component can acquire state or trigger behavior no matter where it is in the tree!

In addition, by defining and isolating concepts in state management and enforcing compliance with certain rules, our code becomes more structured and maintainable.

Features:

  1. Vuex’s state storage is reactive. When the Vue component reads the state from the Store, if the state in the store changes, the corresponding component is updated efficiently accordingly.

  2. You can’t just change the state in the store. The only way to change the state in a store is to commit mutation explicitly. This allows us to easily track each state change, which allows us to implement tools that help us better understand our application

use

To be used in a single page application of Vue, you need to call the plug-in vue. use(Vuex). It’s easy to use, just inject it into the Vue root instance.

import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
    count: 0
  },
getter: {
    doneTodos: (state, getters) => {
      returnstate.todos.filter(todo => todo.done) } }, mutations: { increment (state, payload) { state.count++ } }, actions: {addCount(context) {// can contain asynchronous operations // context is a context object with the same methods and attributes as the store instance}}}) // Inject into the root instance new Vue({el:'#app',
  store,
  template: '<App/>',
  components: { App }
})Copy the code

Then change the state:

this.$store.commit('increment')Copy the code

Vuex has four main parts:

  1. State: YesstoreThe states stored in.
  2. Getter: Similar to a computed property in Vue, the return value is computed based on other getters or states.
  3. Mutation: A group of methods that are changesstoreThe executor of the state in.
  4. Action: A group of methods that can contain asynchronous operations

state

Vuex uses state to store the state that needs to be shared across applications. In order for the Vue component to change after state changes, you need to create computed properties based on state.

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

getters

Similar to computed properties in Vue, they can automatically change after other states or getters change. Each getter method takes state and other getters as the first two arguments

getters: {
    doneTodos: (state, getters) => {
      return state.todos.filter(todo => todo.done)
    }
  }Copy the code

mutations

The first two are state values themselves, mutations is the executor of changing the state. Mutations are used to change state simultaneously

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}Copy the code

The first parameter is state, followed by the other parameters passed in when mutation was initiated.

this.$store.commit('increment', 10)Copy the code

The first parameter to the COMMIT method is the name of the mutation to be initiated, and the remaining parameters are passed into the method defined by the mutation as additional data. The way the specification initiates mutation is as follows:

store.commit({
  type: 'increment',
  amount: 10// This is an extra argument})Copy the code

The additional arguments are wrapped into an object and passed into the mutation defined method as a second argument.

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}Copy the code

actions

To change the state asynchronously, use action. The action does not change state directly, but initiates mutation.

actions: {
  incrementAsync ({ commit }) {
    setTimeout((a)= > {
      commit('increment')},1000)}}Copy the code

The method that initiates the action is of the same form as the mutation method, but with the name Dispatch.

// Distribute store.dispatch({type: 'incrementAsync',
  amount: 10
})Copy the code

Action handles the correct use of asynchrony

Using an Action to handle asynchronous work is as simple as placing an asynchronous operation in an action (such as setTimeout in the code above). There are two ways to proceed with the process after the asynchronous operation completes:

  1. actionReturns apromise.

    dispatchThe essence of a method is to return the correspondingactionThe execution result of. sodispatchAnd return onepromise.
store.dispatch('actionA').then((a)= > {
// ...
})
Copy the code
  1. usingasync/await. The code is much cleaner.
// Suppose getData() and getOtherData() return a Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData'.await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // Wait for actionA to complete
    commit('gotOtherData'.await getOtherData())
  }
}Copy the code

All functions are integrated with Vue components

Combining state and getter into a component requires the use of computed properties:

computed: {
    count () {
      return this.$store. State. The count / / orreturn this.$store.getter.count2
    }
  }
Copy the code

Combining mutation and action into a component requires a call from methods to this. codestore.mit () or this. codestore.mit ():

methods: {
    changeDate () {
        this.$store.commit('change');
    },
    changeDateAsync () {
        this.$store.commit('changeAsync'); }}Copy the code

For simplicity, Vuex provides four ways to easily incorporate these capabilities into components.

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

Sample code:

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

/ /...
computed: {
  localComputed () { / *... * / },
  ...mapState({
    // In order to be able to use 'this' to get local state, you must use regular functions
    count(state) {
      return state.count + this.localCount } }), ... mapGetters({ getterCount(state, getters) {return state.count + this.localCount } }) } methods: { ... mapMutations({add: 'increment' // Map 'this.add()' to 'this.store.mit ('increment')'
    }),
  ...mapActions({
      add: 'increment' // Map 'this.add()' to 'this.$store.dispatch('increment')'})}Copy the code

If you don’t want to change the name after you combine it with a component, you can use an array.

methods: { ... 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)`
    ]),
}Copy the code

Split the Store into modules.

You can split the app store into smaller modules, and each module has everything: State, getters, Mutations, actions. First create a file for the submodule:

// initial state
const state = {
  added: [].checkoutStatus: null
}
// getters
const getters = {
  checkoutStatus: state= > state.checkoutStatus
}
// actions
const actions = {
  checkout ({ commit, state }, products) {
  }
}
// mutations
const mutations = {
  mutation1 (state, { id }) {
  }
}
export default {
  state,
  getters,
  actions,
  mutations
}
Copy the code

Then introduce in the general module:

import Vuex from 'vuex'
import products from './modules/products' // Introduce submodules

Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    products   // Add it to the module}})Copy the code

There is also the concept of namespaces, which are used by large applications. Just review the documentation as needed. The basic use of Vuex is something like this.

reference

https://www.jianshu.com/p/aae7fee46c36

https://vuex.vuejs.org/zh/guide/modules.html