introduce

Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way.

Install Vuex

vue add vuex
Copy the code

Store.js

import Vue from 'vue';
import Vuex from 'vuex';
// Make sure to call vue.use (Vuex) at the beginning
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //this.$store.state.count
    count: 0
  },
  getters: {
    evenOrOdd: (state) = > {
      //this.$store.getters.evenOrOdd
      return state.count % 2= = =0 ? 'even number' : 'odd'}},mutations: {
    increment(state) {
      //this.$store.commit('increment')
      state.count++
    },
    decrement(state) {
      //this.$store.commit('decrement')
      state.count--
    }
  },
  actions: {
    increment({commit}) {
      //this.$store.dispatch('increment')
      // The only way to change the state is to commit mutation
      commit('increment');
    },
    decrement({commit}) {
      //this.$store.dispatch('incrementAsync')
      return new Promise((resolve, reject) = > {
        setTimeout(() = > {
          commit('increment');
          resolve(10);
        }, 1000); }}}})Copy the code

Use this.$store.state to retrieve a state object from a component at an appropriate time, and use this.$store.mit method to violate state changes

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

MapState helper function

When a component needs to fetch multiple states, it can be repetitive and redundant to declare all those states as computed properties. To solve this problem, we can use the mapState helper function to help us generate computed properties

// In the separately built version, the auxiliary function is vuex.mapstate
import {mapState} from 'vuex'

export default {
  / /...
  computed: mapState({
    // Arrow functions can make code more concise
    count: state= > state.count,
    
    // Pass string argument 'count' equal to 'state => state.count'
    countAlias: 'count'.// In order to be able to use 'this' to get local state, you must use regular functions
    countPlusLocalState(state) {
      return state.count + this.localCount
    }
  })
}
Copy the code

We can also pass mapState an array of strings when the name of the computed property of the map is the same as the name of the child node of State.

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

Object expansion operator

The mapState function returns an object. How do we mix it with local computed properties? Typically, we need a utility function to merge multiple objects into one so that we can pass the final object to the computed property. But with the object expansion operator, it’s a lot easier to write

computed: { ... mapState({"count"})}Copy the code

MapGetters helper function

The mapGetters helper function simply maps the getters in the store to local computed properties:

import {mapGetters} from 'vuex'

export default {
	/ /...
	computed: {
		...mapGetters([
			'evenOrOdd'])}}Copy the code

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

mapGetters({
	// map 'this.doneEvenOrOdd' to 'this.$store.getters.evenOrOdd'
	doneEvenOrOdd: 'evenOrOdd'
})
Copy the code

Mutation

The only way to change the state in Vuex’s store is to commit mutation. Mutation in Vuex is very similar to events that have a string of ** event type (type) and a callback function (handler)**. This callback is where we actually make the state change, and it takes state as the first argument.

MapMutation auxiliary function

You can use this. codeStore.mit (‘ XXX ‘) to commit mutation in the component, or use the mapMutations helper function to map methods in the component to a store.mit call (requiring store injection at the root node).

import {mapMutations} from 'vuex'
export default {
	/ /...
	methods: {
		...mapMutations('counter'['increment'.'decrement',])}}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

MapAction helper function

import {mapMutations} from 'vuex'

export default {
	/ /...
	methods: {
		...mapAction('counter'['incrementAsync'])}}Copy the code

submission

// Inside the component
// Distribute in payload form
this.$store.dispatch('incrementAsync', {
  amount: 10
})

// Distribute as objects
this.$store.dispatch({
  type: 'incrementAsync'.amount: 10
})
Copy the code

Module

Because of the use of a single state tree, all the states of an application are grouped into one large object. When the application becomes very complex, the Store object can become quite bloated.

To solve these problems, Vuex allows us to split the Store into modules (moudles). Each module has its own state, mutation, action, getter, and even nested submodules one and the other are split in the same way from top to bottom:

Make a shopping cart example

There are two modules, CART and Products

Create store folder

|--- store
    |--- index.js
    |___ modules
        |--- cart.js
        |___ products.js
Copy the code

cart.js

If you want your modules to be more wrapped and reusable, you can make them namespaced by adding namespaced: True

When a module is registered, all its getters, actions, and mutations are automatically named according to the path the module was registered with.

export default {
	// Make the current module more encapsulation and reuse
	namespaced: true.state: {... },getters: {... },mutations: {... },actions: {... }},Copy the code

products.js

export default {
	// Make the current module more encapsulation and reuse
	namespaced: true.state: {... },getters: {... },mutations: {... },actions: {... }},Copy the code

index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import cart from './modules/cart';
import products from './modules/products';
export default new Vuex.Store({
	modules: {
		cart,
		products,
	}
})
// This.$store.state
// This.$store.state. Products // Get the status of products
Copy the code

When should I use Vuex?

Vuex helps us manage shared state and comes with more concepts and frameworks. This requires a trade-off between short-term and long-term benefits.

Using Vuex can be tedious and redundant if you don’t plan to develop large, single-page applications. That’s true — if your application is simple, you’d better not use Vuex. A simple Store pattern is all you need. However, if you need to build a medium to large single-page application, and you’re probably thinking about how to better manage state outside of components, Vuex would be a natural choice. To quote Redux author Dan Abramov:

Flux architectures are like glasses: Do you know when you need them

The plug-in

The log plug-in

Vuex comes with a logging plug-in for general debugging:

import createLogger from 'vuex/dist/logger'
const store = new Vuex.store({
	plugins: [createLogger({
		collapsed: false.// Automatically expand the mutation of the record})]})Copy the code

Note that the Logger plug-in generates state snapshots, so it is only used in development environments.