Vue (Vuex plugin)

1. Introduction to Vuex

1. Concept

A Vue plug-in that specifically implements centralized state data management in Vue. It performs centralized management (read/write) on the shared state of multiple components in Vue applications. It is also a way of communication between components, and Suitable for communication between arbitrary components.

2. Understand vuex address

https://github.com/vuejs/vuexhttps://github.com/vuejs/vuex

3. Image form understanding vuex

When passing information through the global event bus or message subscription and publishing, multiple components must be sent one by one, and if modified, they must be modified one by one

  • vuex can solve the disadvantage of sending one by one

So the main usage scenarios of vuex are:

  • When multiple components depend on the same state
  • The behavior of several different components needs to become more same

4. Understanding through examples:

Pure vue case: calculation

<template>
  <div>
  <h1>The current sum is: {<!-- -->{sum}}</h1>
  <select v-model.number="n">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <button @click="increment"> + </button>
  <button @click="decrement">-</button>
  <button @click="incrementOdd">The current page is base + </button>
  <button @click="incrementWait">Wait a while before + </button>
  </div>
</template>

<script>
export default {
  name:'Count',
  data() {
    return {
      n:1, //Number selected by the user
      sum:0
    }
  },
  methods: {
    increment(){
      this.sum + = this.n//Note that characters will be spliced,
      //Because the option data is not bound, the js expression is inside the quotation marks after binding
      //Use the modifier to convert the data into a value
    },
    decrement(){
       this.sum -= this.n
    },
    incrementOdd(){
      //The remainder calculation is used here. If it is equal to 0, it will not enter the judgment when converted to a Boolean value
      if(this. sum % 2){
        this.sum += this.n
      }
    },
    incrementWait(){
      setTimeout(()=>{
        this.sum += this.n
      },500)
    },
  },
 
}
</script>
  • Bind the data first
  • Lay out the page and set the button execution event
  • Set the logic to execute the event
  • There is a problem: when binding data, it is not a value
    • Utilization: bind value value
    • Or use the modifier directly: number

5. Vue working principle diagram

Important components of vuex: Actions, Mutations, State

  • State: object, which can save many key-value default values

  • Component: There are various methods in the component, call api-dispatch (‘action type’, action value)

  • Actions: object object, match the key with the above action type, then call the function corresponding to the key, and then call commit (submit) by yourself

  • Mutations: object object, there is also a key on this object and the above action type pair, and then call the function corresponding to the key, the function contains (the entire state, action value) automatically mutate

  • Then the state will change, and then parse again

Action, ajax gets backend API to get data on other servers

When the value of the Action is known by itself, then the component can be executed directly to commit to Mutations

Devtools: talk directly to mutations

Simple understanding:

component === guest

Action === waiter

Mutations === back kitchen

State === dish

2. Use of Vuex

1.vuex development environment construction

  • Install vuex: Note that vue3 has become the default version, and vuex has been updated to version 4 (install vuex3 in the vuex2 project)

npm i vuex@3
  • The use of plug-ins: the purpose is to have store configuration in vm after using vuex

    • introduce vuex in main

    • Use vuex, import and use it in the main file and omit it (because it will report an error)

    • Then configure the store in the vue instance

Note: If vuex is not introduced and used, then no store configuration will be generated in vm or vc

Even if many custom matching items are configured in the vm instance, if the vm does not recognize it, it will be discarded

new Vue({
    el:'#app',
    render: h => h(App),
    //store:'hello',//The store cannot be found in the component before vux is introduced
    store,//Shorthand way: it needs to be introduced and used in main before it can be configured, and then it will appear in vc and vm
    },
})
  • Configure the store file: seeing the store is equivalent to seeing the waiter, kitchen, and dishes of vuex

    • Configure the store file in src
    • Then create index.js file in it

  • Set store:

    • Configure the above three important components

    • Then introduce vuex and instantiate it (note that the store is instantiated) and expose it

    • Then put the configuration in the instance (shorthand method: the key value can be shortened if the key value is equal)

//Introduce vuex
import Vuex from 'vuex'


//Configure actions--used to respond to actions in components
const actions = {}
//Prepare mutations--for manipulating data
const mutations = {}
//Prepare state--used to store data
const state = {}



//Create and expose store
export default new Vuex. Store({
  actions,
  mutations,
  state,
})
  • Then introduce store in the main file

// import store
// The file after import store from './store/index' can be omitted (must be index)
import store from './store'

Error: Vue.use(vuex) should be instantiated before store

  • So do not introduce vuex and use it in main (the error mentioned above)

  • Because when the store is introduced, it will be automatically parsed before using vuex

  • Introduce vue and vuex directly into the store file, and use vue.use(vuex)

import Vue from 'vue'
//Introduce vuex
import Vuex from 'vuex'
// Use the plugin to use vuex between creating the store
Vue. use(Vuex)

2. Vuex writes the above calculation case (only one component is used to understand the vuex working process: only write addition here: to understand the calculation method) and the subtraction is the same

  • First put the data in the state, and then the calculation of the sum in the component cannot be performed
  • The setting method in the component is passed to actions
increment(){
 // here you can directly execute mutations to get data execution method without using actions
     this.$store.dispatch('jia',this.n)
    },
  • Configuration method in actions: There are two parameters in the method, which are the context and the incoming value
  • And do the calculations in the upload context
 //Two parameters: one is miniStore (context), followed by value
 jia(context, value) {
    console. log(context, value);
    context.commit('JIA',value)
  },
  • The calculation method needed to configure the context in mutation
  • The calculation method in the mutation should be uppercase (easy to watch)
  • One of the parameters of the method in the mutation is state, and the other is the value passed in
JIA(state,value) {
    // console.log(state,value); The parameters are the data in the data monitoring state and the parameters passed in
    state.sum += value
  },
  • The page reading effect should be obtained from the component, obtained directly, without this acquisition
  • The display initial value is set according to the configuration in vuex
<h1>The current sum is: {<!-- -->{$store.state.sum}}</h1>

3. Configure odd addition and first-class calculation

  • Directly pass in the vuex calculation method in the component
 incrementOdd(){
      this.$store.dispatch('jiaOdd',this.n)
     
    },
 incrementWait(){
      this.$store.dispatch('jiaWait',this.n)
    },
  • Configure the calculation method in the actions of the store file: odd number calculation and first-rate calculation
 jiaOdd(context, value) {
    if (context. state. sum % 2) {
      // The context directly submits the execution action
      context.commit('JIA', value)
    }
  },
jiaWait(context, value) {
    setTimeout(() => {
      context.commit('JIAN',value)
 },500)
 },
  • The method in mutations is still the method configured above
const mutations = {
  JIA(state, value) {
    state.sum += value
  },
  JIAN(state,value) {
    state.sum -= value
  }
}

4. Optimize vuex matching process

The calculation method that can be obtained directly from mutations: Use commit directly in the component to obtain

increment(){
   this.$store.commit('JIA',this.n)
},
decrement(){
   this.$store.commit('JIAN',this.n)
}, 

Both JIA and JIAN above exist in mutations

5. Explanation of developer tools

Simple understanding of developer tools

  • Talk directly to mutations, and the final calculation is through the calculation in mutations

Operations for each step in the developer tool

  • Stopwatch button: directly restore to the specified calculation effect
  • Clear effect: directly delete the current calculation effect (delete the middle one, all the previous ones will be cleared)
  • Download button: Merge all calculation steps before the current click, and merge

Three buttons in the upper right corner

  • Red dot: will not capture calculation step
  • Clear button: Clear all operation records
  • Download: Combine all steps

Two buttons in the lower right corner

  • Export: copy the final effect of the calculation process (exist in the clipboard)
  • Import: Paste directly in the import box (Esc to exit)

6. Several questions used in vuex

Why do you need the context parameter in actions

When the business logic is more complicated, you need to execute some things in the outermost layer first, and then dispatch a certain method

Then handle a little more things in the second layer, and then call dispatch

The last layer performs a little thing and then executes commit

Why commit the simple calculation method to mutations

If you perform odd calculations, you don’t need to use commit to submit to mutation, you can directly use state to calculate

context.state.sum += value can be executed but not standardized (developer tools can not capture)

Why write logic in actions instead of component methods

If the action to be executed requires multiple servers to make judgments, writing in its own component cannot achieve multiplexing

7.getters configuration item, in store

It does not have to exist, if you want to perform some complex operations on the state default data, it will reflect its role

  • The parameter is the data in the state, and the return value is used for calculation
// Prepare getters for direct processing of data in state
const getters = {
  // The state parameter is the state
  bigSum(state) {
    return state. sum * 10
  }
}
  • configure and expose
export default new Vuex. Store({
  actions,
  mutations,
  state,
  getters,
})
  • template acquisition
 <h3>The current sum is enlarged by 10 times: {<!-- -->{$store.getters.bigSum}}</h3>

3. Optimize the use of vuex

The following content is completed in the construction

1. mapState and mapGetters

Optimizing Fetching Data and Optimizing Complex Operations on Data: The Rough Approach

Directly use the calculated property to get the sum: the state from the store of the current component

The template is simple, but the code is still redundant

There is a way to get data and name it yourself

mapState: mapping data

  • import first
import {mapState} from 'vuex'
  • Acquisition in computed properties (object and array methods for acquisition)
  • Use the remaining parameters to obtain, and the final display through the developer tool is the binding of vuex
//Use mapstate to obtain data from the state (object writing): the name of the calculated attribute is different from the name of the obtained data
...mapState({he:'sum',xuexiao:'school',xueke:'subject'})
//Get the value through an array (the name of the calculated attribute is the same as the name of the obtained data)
 ...mapState(['sum','school','subject']),

mapGetters

  • First introduce mapGetters
import {mapGetters} from 'vuex'
  • Get it in a computed property
computed:{
...mapGetters({beishu:'bigSum'}),//object writing
  ...mapGetters(['bigSum']),//array writing
}

2. mapMutations and mapActions

mapMutations

  • First introduce mapMutations
import {mapMutations} from 'vuex'
  • Acquisition in the method: Note that there will be problems: the acquired mouse event has no value
  • Pass data directly in the template
 <button @click="increment(n)"> + </button>
  <button @click="decrement(n)">-</button>
...mapMutations({increment:'JIA', decrement:'JIAN'}),//object writing
...mapMutations(['JIA','JIAN']),//array writing (the name after using the array import is the imported name)

mapActions

  • First introduce mapActions
import {mapActions} from 'vuex'
  • Acquisition in the method: first use the template to pass the data
 <button @click="incrementOdd(n)">The current page is base + </button>
 <button @click="incrementWait(n)">Wait a while before + </button>
 ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),//object form
  ...mapActions(['jiaOdd','jiaWait']),//Array form, note that no name is generated

The above two passed values can be obtained not only through the template, but also directly through the method (not used)

increment(){
  this. Receive custom name (value value)
}

4. Multiple components share data

Create a new person component: configure a different page effect

Configure components and vuex

  • The state data configures an object, which can be traversed and obtained in the component, and the calculated property can directly simplify the traversal and obtain the source
//store data writing
 personList: [
    {id: '001',
    name:'Zhang San'}
  ]

//Loop through the names in the component
 <ul>
     <li v-for="p in personList" :key='p.id'>{<!-- -->{p.name}}</li>
 </ul>

//retrieve data
personList(){
        // Note that you need to use return to get the data
        return this.$store.state.personList
 },
 // retrieve data
 // ...mapState(['personList'])
  • Configuration button click method: rely on the new object generated by nanoid and commit
  • Add a method directly in mutations (add people to data)
 add(){
      const personObj = {id: nanoid(), name: this.name}
      this.$store.commit('ADD_PERSON', personObj)
      this.name = ''
  }

//vuex
 ADD_PERSON(state, value) {
    state.personList.unshift(value)
  }

Then get the number of people in the data through the simple method of getting data above, and you can use it in other components

5. vuex modularity

The vuex data and methods used by different components in vuex are different: multiple different vuex contents are mixed together and easily confused

1. Distinguish component objects (name) and configure namespaced configuration (enable namespace)

  • Make a distinction: only the person-vuex module is demonstrated here
  • Determine the classification: configuration item namespaced: true default value false
  • Only by obtaining the modular name in the above configuration components will it be recognized
const personOptions = {
  namespaced: true, //The default value here is false
  actions: {
    // If the king is included: judge that 0==0 is correct, then submit and use the mution method
    addPersonWang(context, value) {
      if (value.name.indexOf('King') === 0) {
        context.commit('ADD_PERSON', value)
      } else {
        alert('Add a person surnamed Wang')
      }
    }
  },
  mutations: {
    ADD_PERSON(state, value) {
      state.personList.unshift(value)
    }
  },
  state: {
    personList: [
      {id: '001',
      name:'Zhang San'}
    ]
  },
}

2. Expose component modules and configure custom names

  • The exposure in the store after the distinction is not directly exposing the vuex configuration: use the modules configuration to distinguish
  • Note that there will be problems with acquisition after modularization: data and actions cannot be acquired
  • But after the component is modularized, there is a custom name
//Create and expose store
export default new Vuex. Store({
  // Expose the configuration of the store: after the above configuration is named, the following will recognize it
  modules: {
    countAbout: countOptions,
    personAbout:personOptions
  }
})

3. To obtain the data in the module, you need to distinguish the module first and then import it

  • Then the template in the component directly obtains the data: the simple method needs to cooperate with the custom name above
 ...mapState('countAbout',['sum','school','subject','personList']),
  ...mapState('personAbout',['personList']),
computed:{
    ...mapState('countAbout',['sum','school','subject','personList']),
    ...mapState('personAbout',['personList']),
    ...mapGetters('countAbout',['bigSum']),//array writing
  },
  methods: {
      ...mapMutations('countAbout', {increment:'JIA', decrement:'JIAN'}),//object writing
   
     ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'}),//object form
      
  },

4. The code format when obtaining data and methods in vuex through native methods and adding them

Note that / is used here to split

//Get the data in vuex
computed: {
      personList(){
        // Note that you need to use return to get the data
        return this.$store.state.personAbout.personList
      },
}
//The code format when acquiring the data in the modular vuex and executing the mutations method
 add(){
      const personObj = {id: nanoid(), name: this.name}
      this.$store.commit('personAbout/ADD_PERSON',personObj)
      this.name = ''
    },

5. Obtain getters in modularization through native methods

When obtaining data, you need to obtain object data through [] Method: Wrap the custom name exposed by the component module

//The above component has been configured to add the first and last name of Wang
//Configure getters in the component module - get the first name
getters: {
    firstPersonName(state) {
      return state.personList[0].name
    }
  },
//used in components
 computed: {
   firstPersonName(){
        // get object method array get
        return this.$store.getters['personAbout/firstPersonName']
      }
  },

6. Optimize modular code

Create a separate vuex file: put the vuex configuration in it and expose it

Create a general vuex:

  • Introduce a single vuex in the total file
  • and expose
//This file creates the most important store of vuex
import Vue from 'vue'
//Introduce vuex
import Vuex from 'vuex'
// Import store module
import countOptions from './count'
import personOptions from './person'
// Use the plugin to use vuex between creating the store
Vue. use(Vuex)

//Create and expose store
export default new Vuex. Store({
  // Expose the configuration of the store: after the above configuration is named, the following will recognize it
  modules: {
    countAbout: countOptions,
    personAbout:personOptions
  }
})

7. The server obtains the name of the person – write in the corresponding component

A free api is used here:

https://api.uixsj.cn/hitokoto/get?type=socialhttps://api.uixsj.cn/hitokoto/get?type=social

//Introduce nanoid first
import { nanoid } from "nanoid"


//actions
 addPersonServe(context) {
      // Send get request to get data
      axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
        response => {
          context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
        },
        error => {
          alert(error. message)
        }
      )
    },
//Setting method in component
  <button @click="addPerson">Add a person with a random name</button>

//Get the method in actions
 addPerson(){
      this.$store.dispatch('personAbout/addPersonServe')
    }

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge Vue entry skill tree VueX state managementWhat is VueX? 33155 people are studying systematically