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