What is Vuex?

Vuex is a state management mode developed specifically for vuue.js applications. Vuex is a global state management mode

What is Vuex used for?

Vuex is used to transfer values between components, and multiple components share data. The data of Vuex is responsive. When we update A state in component A, component B will update dynamically

State

State is used to store State

In the componentVuexstate

Since Vuex’s state store is reactive, the easiest way to read state from a Store instance is to return some state in a calculated property:

computed: {
  count: () = > store.state.count
  // Or "injects" state from the root component into each child component vue.use (Vuex)
  count: () = > this.$store.state.count
},
Copy the code

MapState Indicates the obtaining mode

import { mapState } form 'vuex'

computed: {
	...mapState({
	    // 1. Basic usage store/index.js
            isLogin: (state) = > state.isLogin
            // 2. Use the module store/modules/user.js
            isLogin: (state) = > state.user.isLogin
	}),
},
Copy the code

Getters

Getters is similar to computed properties and is reevaluated only when its dependencies change

The Getter accepts state as its first argument:

const store = new Vuex.Store({
  state: {
    todos: [{id: 1.text: '... '.done: true },
      { id: 2.text: '... '.done: false}},getters: {
    doneTodos: state= > {
      return state.todos.filter(todo= > todo.done)
    }
  }
})
Copy the code

Used in components

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}
Copy the code

MapGetters Indicates the method of obtaining the file

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    // Mix getters into a computed object using the object expansion operator. mapGetters(['doneTodosCount'.'anotherGetter'.// ...
    ])
    // Use Modules store/user.js. mapGetters('user'['increment'.'incrementBy'.// ...])}}Copy the code

Mutations

The only way to change the state in the Store is mutations

The first parameter on mutations is state

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // Change the state
      state.count++
    }
  }
})
Copy the code

A method is called

store.commit('increment')
Copy the code

You can pass extra parameters to store.mit

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

Remember that Mutation must be a synchronization function

Commit Mutation in the component

computed: {
  doneTodosCount () {
    return this.$store.commit('increment')}}Copy the code

Submit via mapMutations

import { mapMutations  } from 'vuex'

export default {
  // ...
  methods: {
    // Mix getters into a computed object using the object expansion operator. mapMutations(['increment'.'incrementBy'.// ...
    ])
    // Use Modules store/user.js. mapMutations('user'['increment'.'incrementBy'.// ...])}}Copy the code

Action

Action is similar to mutation, except that:

  • The Action commits mutation rather than a direct state change.
  • Actions can contain any asynchronous operation.

Register a simple action:

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

The Action function accepts a context object with the same methods and properties as the store instance, so you can submit a mutation by calling context.mit. Or get state and getters via context.state and context.getters.

In practice, we often use ES2015’s parameter deconstruction new Window to simplify code

actions: {
  increment ({ commit }) {
    commit('increment')}}Copy the code

Trigger an Action in the component

methods: {
  increment () {
    this.$store.dispatch('increment')}}Copy the code

Triggered in mapActions mode

import { mapActions  } from 'vuex'

export default {
  // ...
  methods: {
    // Mix getters into a computed object using the object expansion operator. mapActions(['increment'.'incrementBy'.// ...
    ])
    // Use Modules store/user.js. mapActions('user'['increment'.'incrementBy'.// ...])}}Copy the code

Combination of the Action

Sometimes you need to combine multiple actions, such as calling actionA in actionB

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) = > {
      setTimeout(() = > {
        commit('someMutation')
        resolve()
      }, 1000)}}}Copy the code

With async/await, we can combine actions as follows:

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) = > {
      setTimeout(() = > {
        commit('someMutation')
        resolve()
      }, 1000)})}async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // Wait for actionA to complete
    // ...}}Copy the code

Modules

When the application becomes very complex, the Store object can become quite bloated. Modules splits the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules.

const moduleA = {
  state: () = >({... }),mutations: {... },actions: {... },getters: {... }}const moduleB = {
  state: () = >({... }),mutations: {... },actions: {... }}const store = new Vuex.Store({
  modules: {
    moduleA,
    moduleB
  }
})
Copy the code

Project Use Case

@ / store/modules/user. Js:

export default {
    namespaced: true.state: {
        // Store the state
        isLogin: false
    },
    mutations: {
        // Change the status
        SET_ISLOGIN(state, val) {
            state.isLogin = val
        }
    },
    actions: {
        // Asynchronous operation
        login({ commit }, query) {
            api.login({
                code: query.code,
                iv: query.iv
            }).then(res= > {
                commit('SET_ISLOGIN'.true)})}}}Copy the code

@/store/index.js :

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'

/ / Vuex installation
Vue.use(Vuex)

// Create a store
export default new Vuex.Store({
  modules: {
    user,
    // ...}})Copy the code

@/main.js :

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from '@/store';

new Vue({
    router,
    store,
    render: h= > h(App)
}).$mount('#app');
Copy the code