Preface:

In the development of SPA single-page components, both VUex of Vue and Redux of React are called the same state management. Personally, I think global state management is more appropriate. The simple idea is that once you define a piece of data in state, you can retrieve and modify it in any component of your project, and your changes can be globally responsive to changes.

A, install,

`npm install vuex --save`  or  `yarn add vuex`
Copy the code

Second, the use of

Create the file SRC /store/index.js

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

const store = new Vuex.Store();

export default store
Copy the code

Store is added to main.js and is injected globally so that each component can use this.$store

Import store from './store' new Vue({el: "#app", store, // inject store router, // Route templat: "< app />", Component :{app}})Copy the code

In store/index.js, we declare a state variable and assign an empty object to it. In store/index.js, we define two initial property values. Then pass an empty object in the instantiated vuex. Store and place the variable stater in it:

1. state

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state = { 
    // The state object for global access to set
     showFooter: true.changableNum:0
     // The initial property value to set
   };
 const store = new Vuex.Store({
       state
    });
 
export default store;
Copy the code

This.$store.state.showFooter or this.$store.state.changebleNum can be used in either of the components to obtain the values defined by showFooter and changebleNum, but this is not ideal; Vuex’s official API provides a Getters, which, like Vue calculates a computed property, listens for changes in state (the latest state) in real time and puts it in vuex.store.

2. getters

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state = {   
 // The state object for global access to set
     showFooter: true.changableNum:0
     // The initial property value to set
   };
const getters = {   
    // Monitor state changes in real time
    isShow(state) {  
    // The method name is arbitrary, mainly to carry the changing value of showFooter
       return state.showFooter
    },
    getChangedNum(){  
    // The method name is arbitrary, mainly used to carry the changing value of changableNum
       return state.changebleNum
    }
};
const store = new Vuex.Store({
       state,
       getters
});
export default store;
Copy the code

Mutations, mutattions is also an object, and there are methods in this object that can change the initial value of state, This is done by passing state or extra arguments to the methods inside, and then using vUE’s two-way data drive to change the value.

3. mutations

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state = {   
 // The state object for global access to set
     showFooter: true.changableNum:0
     // The initial property value to set
   };
const getters = {   
// Monitor state changes in real time
    isShow(state) {  
    // The value of showFooter to carry the change
       return state.showFooter
    },
    getChangedNum(){  
    // The value of changebleNum to carry the change
       return state.changableNum
    }
};
const mutations = {
    show(state) {   
    // Define the method to change the initial value of state, where the parameters can be passed additional parameters (variables or objects) in addition to state;
        state.showFooter = true;
    },
    hide(state) {  
    / / same as above
        state.showFooter = false;
    },
    newNum(state,sum){ 
    // add sum to statestate.changableNum+=sum; }};const store = new Vuex.Store({
       state,
       getters,
       mutations
});
export default store;
Copy the code

Use this. Codestore.com MIT (‘show’) or this. Codestore.com MIT (‘hide’) and this. Codestore.com MIT (‘newNum’,6) Change showFooter and changebleNum values in other components, but this is not the ideal way to change values; Because the mutations methods in Vuex are all synchronous transactions, that means, for example, this.$store.com MIT (‘newNum’,sum) method, which uses the same value for each component each time, is definitely not ideal

Vuex official API also provides an Actions, which is also an object variable. The biggest effect of actions is that the Action method can contain any asynchronous operation. The method mentioned here is used to trigger the method in mutations asynchronously. A custom function in actions takes a context parameter and the parameter to change. Context has the same methods and properties as the store instance, so it can call context.mit (“).

4. actions

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 const state = {   
 // The state object for global access to set
     showFooter: true.changableNum:0
     // The initial property value to set
   };
const getters = {   
// Monitor state changes in real time
    isShow(state) {  
    // The value of showFooter to carry the change
       return state.showFooter
    },
    getChangedNum(){  
    // The value of changebleNum to carry the change
       return state.changableNum
    }
};
const mutations = {
    show(state) {   
    // Define the method to change the initial value of state, where the parameters can be passed additional parameters (variables or objects) in addition to state;
        state.showFooter = true;
    },
    hide(state) {  
    / / same as above
        state.showFooter = false;
    },
    newNum(state,sum){ 
    // add sum to statestate.changableNum+=sum; }};const actions = {
    hideFooter(context) {  
    // Customize the method that triggers the function in mutations. Context and store instances have the same methods and attributes
        context.commit('hide');
    },
    showFooter(context) {  
    // Same as above
        context.commit('show');
    },
    getNewNum(context,num){   
    Num is the parameter to be changed
        context.commit('newNum',num)
     }
};
 const store = new Vuex.Store({
       state,
       getters,
       mutations,
       actions
});
export default store;
Copy the code

When other components perform actions globally, you just use actions

This.$store.dispatch(‘hideFooter’) or this.$store.dispatch(‘showFooter’) and this.$store.dispatch(‘getNewNum’, 6) //6 arguments to change

/ / case:  <template> <div id="app"> <router-view/> <FooterBar v-if="isShow" /> </div> </template> <script> import FooterBar from '@/components/common/FooterBar' import config from './config/index' export default { name: 'App', components:{ FooterBar }, data(){ return { } }, computed:{ isShow(){ return this.$store.getters.isShow; }}, watch:{$route(to,from){ Monitor routing parameters corresponding to the current page and a page on the console. The log (to) the if (to.. name = = 'book' | | to.. name = = 'my') {/ / to. The name for the current page, shown by the This.$store.dispatch('showFooter')}else{ this.$store.dispatch('hideFooter') } } } } </script>Copy the code

5. module

Modules and the introduction of mapGetters, mapActions, and mapStates into components

Because in most projects, we don’t manage global state for just one situation, sometimes there are multiple requirements, like when you’re writing a mall project, you might use global state for shopping cart or you might use global state for price; In cases like this we should consider using Modules in VUex.

// The file can be overwritten
import Vue from 'vue';
import Vuex from 'vuex';
import footerStatus from './modules/footerStatus'
import collection from './modules/collection'
Vue.use(Vuex);

export default new Vuex.Store({
    modules:{
         footerStatus,
         collection
    }
});
Copy the code
<template> <div id="app"> <router-view/> <FooterBar v-if="isShow" /> <p>{{this.$store.state.footerStatus.showFooter}}</p> </div> </template> <script> import {mapState,mapGetters,mapActions}  from 'vuex'; / / want to introduce first import FooterBar from '@ / components/common/FooterBar import config from'. / config/index 'export default {name: 'App', components:{ FooterBar:FooterBar }, data(){ return { } }, computed:{ ... MapState ({// here... It's an overreference, ES6 syntax, Mean how many attribute values in the state isShow: how can I put here attribute value state = > state. FooterStatus. ShowFooter / / note that these above is the difference between a state. The footerStatus, Footerstatus.js showFooter}),}, watch:{ $route(to,from){ if(to.name=='book'||to.name=='my'){ this.$store.dispatch('footerStatus/showFooter') // I'm going to say 'footerStatus/showFooter', }else{this.$store.dispatch('footerStatus/hideFooter')}}}}} </script>Copy the code

Conclusion:

After self-practice, if you want to use VUEX well, you need to master the following points:

  1. Component data sharing, cross-page data sharing, unified management of data storage, operation, distribution. For example, user data, for example, fixed some data is retrieved by certain apis and is not used for one component or one scenario;
  2. Don’t be formalistic, use Vuex for every page; Write getters, Actions, constant methods for each module. When you have enough engineering and data to use a certain technical scenario, it feels appropriate to use a certain solution.
  3. Handles data-based business logic, typically across pages and components, such as the linkage effect of the purchase process on user balances, shopping carts, and orders;
  4. Vuex core index to do some module common storage tools, you can configure some needed plug-ins or tool classes;
  5. Expansion: Data communication is not only vuEX, simple event bus can also be used, even the page can meet your needs;