What is Vuex?
Vuex It is a state management mode specially developed for Vue.js application. It adopts centralized storage to manage the state of all components of the application and solve multi-component data communication.
main points:
-
vue is officially matched and used exclusively (similar to vue router), with special debugging tools
-
Centralized management data status scheme (simpler operation) data() {return {data, status}}
-
Data changes are predictable (responsive)
vue is an official tool for managing public data independent of the component system
There are five things to learn in Vuex:
-
state: unified definition of public data (similar to data(){return {a:1, b:2, xxxxx})
-
Variations: use it to modify data (similar to methods)
-
getters: similar to computed (calculate attributes, calculate the existing state to get new data ------ derivation)
-
actions: initiate asynchronous requests
-
modules: module splitting
-
The most important contents are state and changes, which need to be mastered
Steps for using Vuex:
- Download Vuex
npm i vuex perhaps yarn add vuex
two Create a unified folder store under the src directory, and create index.js in the store
three Place specific code in store/index.js, as follows:
import Vue from "vue" import Vuex from "vuex" Vue.use(Vuex) export default new Vuex.Store({ state: {}, mutations: {}, getters: {}, actions: {}, modules: {} })
Note: don't forget to inject store into Vue instances
In src/main.js:
-
Import store
-
And inject Vue instances
import store from './store' new Vue({ render: h => h(App), store }).$mount('#app')
1. stateĀ
vuex uses it to store public data
Format:
new Vuex.store({ state: { Attribute name: attribute value } })
Use common data format:
In the component, access it through the 'this.$store.state. Attribute name'.
In the template, you can omit 'this' and write it directly as ` {{$store.state. Attribute name}}`
Example:
export default new Vuex.Store({ state: { num: 8 } )}
Next, get and use this common data in the template
<template> <div> {{ $store.state.num }} // 8 will be printed on the page </div> </template>
2.mutations
Changes is mainly used to modify public data in state
Define format:
nwe Vue.State({ mutations: { // Each item is a function that can declare two formal parameters mutation Name 1: function(state ,[load]) { }, mutation First name 2: function(state ,[load]) { } } })
Each item is a function that can declare two formal parameters:
-
The first parameter is required and represents the current state. No need to pass in when using
-
The second parameter is optional and represents the load. Data to be passed in when using
Use format:
this.$store.commit('mutation name', Argument, give the second argument)
commit here is a fixed method.
Example:
export default new Vuex.Store({ state: { num: 8 }, mutations: { dobuleNum: function(state) { state.num *= 2 }, } })
Next, define a button button in App.vue and click to double num,
Note: in the template, do not add 'this'----- $ store.commit('changes name ')
In the component, you need to add this call
<template> <div> {{ $store.state.num }} <!-- Use global mutations --> <button @click="$store.commit('dobuleNum')">overall situation mutations Modify data</button> </div> </template>
3.getters
getters is used to further process the data based on the data in state to get new data. (same as calculated attribute in component)
Define format:
new Vuex.store({ // Omit other getters: { // State is the public data state defined above getter Your name 1: function(state) { return Value to return } } })
Use format:
In the template by: $store.getters.getter Name to access
Example:
export default new Vuex.Store({ state: { num: 8 }, getters: { tenfold(state) { return state.num * 10 } } })
Then use it directly in App.vue
<template> <div> <p>Use global getters:{{ $store.getters.tenfold }}</p> </div> </template>
4.actions
We can use Action to modify state, which is similar to mutation, except that:
-
In action, you can modify the state by calling mutation instead of directly changing the state.
-
An action can contain any asynchronous operation, such as an ajax request.
Define format:
new Vuex.store({ // Omit other actions: { // The context object is automatically passed in, which has the same methods and properties as the store instance action Name of: function(context, load) { // 1. Send asynchronous request to request data // 2. commit calls mutation to modify / save data // context.commit('mutation name ', payload) } } })
Use format:
Pass in component`this.$store.dispatch('actions Name of', parameter)`To call action Through the module`$store.dispatch('actions Name of', parameter)`To call action
Example:
export default { state: { books: [] }, mutations: { setBooks(state, newBooks) { state.books = newBooks; } }, actions: { getBooks(context) { axios({ method: "get", url: "https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books" }).then(res => { console.log(res); context.commit("setBooks", res.data.data); }) } } }
Note: in state, I define an array book: [] to receive the acquired data. After receiving the data res, I want to assign it to the book array, but remember that assignment cannot be performed directly. You must define an assignment function in changes and obtain the data in actions. Call the function in changes to assign the value
Next, create a button in App.vue, click the button to trigger actions, initiate axios request to obtain data, and assign it to the book array
<template> <div> // Trigger actions and initiate axios to request data <button @click="$store.dispatch('getBooks')"> Click to get book information </button> </div> </template>
5.modules
modules is used to split the code in index.js, reduce the complexity and volume of the code in index.js, make index.js more concise, and extract the same required data and methods into the same JS
Modules default named: false. When true is set, the module name should be added to the data and methods split into modules in the component
First, create a modules folder under the store folder, then customize a getBooks.js file under the modules folder, and then Cut the relevant code in state, variations, getters and actions into the getBooks.js file
import axios from "axios"; export default { namespaced: true, state: { skills: ["vue", "html", "js"], nubs: 20, books: [] }, mutations: { setBooks(state, newBooks) { state.books = newBooks; }, change(state, newSkills) { state.skills = newSkills; } }, getters: { sum(state) { return state.nubs + 10; } }, actions: { getBooks(context) { axios({ method: "get", url: "https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books" }).then(res => { console.log(res); context.commit("setBooks", res.data.data); }); } } }
After being extracted into getBooks.js, it is introduced in index.js and added to the modules object
import Vue from 'vue' import vuex from 'vuex' import getBooks from './modules/getBooks.js' Vue.use(vuex) export default new vuex.Store({ modules: { getBooks } })
Note: after you detached, the way of invocation in the component changed. Remember that when we added namespaced: true, we must add module names when we add data and methods.
Use format:
To access the data in the module, add the module name
Get data item: {{$store.state. Module name. Data item name}}
Get getters: {{$store.getters ['module name / getters name']}}
Access the changes / actions in the module:
-
If named is true, the module name needs to be supplemented additionally
-
If named is false, no additional module name is required
$store. Commit ('changes name ') // Named is false
$store.commit('module name / changes name ') // Named is true
The code is more intuitive. For example:
// example: 1. Original writing: <p>{{$store.getters.sum}} </p> // 30 2. Detached writing: <p>{{$store.gerters['getBooks/sum']}} </p> // 30 // Here I'll list the other three ways // state: <p>{{ $store.state.getBooks.skills[0] }}</p> // mutations: <button @click="$store.commit('getBooks/change',['css','Applet','react'])"></button> // actions: <button @click="$store.dispatch('getBooks/getBooks')"></button>
Add: if you want to modify the name of state / changes / getters / actions, for example, you can write $store.commit('module name, {new name, old name} '), and other formats are similar
When using modules, it is recommended to add named!
Summary of auxiliary function map series usage of Vuex
mapState/mapMutations/mapGetters/mapActions
It is used to optimize the access method. The common writing method is too troublesome. Using the built-in method of vuex, you can simply reference the data and methods in vuex
1. mapState function
Map the variables in state to the variables used in the current component
Use the following steps:
// In index.js export default new vuex.Store({ state: { num: 10 } }) // In App.vue <template> <div> {{ num }} // 10 </div> </template> <script> // Import the auxiliary function mapState, which is a tool function defined in vuex. import { mapState } from 'vuex' export default { computed: { ...mapState(['num']) // If you need to change your name ...mapState({ 'New name': 'Old name' }) } } </script>
computed: {... mapState()} here... Is the expansion operator of objects. On the whole, it is the merging of objects
2. mapMutations
// Define a variable in state as a:10 // In App.vue component <template> <div> {{a}} <button @click="add">click+1</button> </div> </template> <script> import { mapMutations, mapState } from 'vuex' export default { computed: { ...mapState(['a']) }, methods: { ...mapMutations(['add']) }, } </script> // In index.js export default new vuex.Store({ state: { a: 10, }, mutations: { add: function (state) { state.a += 1 } }, })
The above lists the syntax of mapState and mapMutations. The usage of the other two (mapGetters and mapActions) is the same as the first two. Experience it yourself
Next, let's talk about the usage of map series in global and modules situations:
Start with the above figure:
How to use global state
-
Direct use: this.$store.state.xxx;
-
map auxiliary function:
computed: { ...mapState(['xxx']), ...mapState({'New name': 'xxx'}) }
How to use state in modules
-
Directly use: this.$store.state. Module name. xxx;
-
map auxiliary function:
computed: { ...mapState('Module name', ['xxx']), ...mapState('Module name', {'New name': 'xxx'}) }
How to use global getters
-
Direct use: this.$store.getters.xxx
-
map auxiliary function:
computed: { ...mapGetters(['xxx']), ...mapGetters({'New name': 'xxx'}) }
How to use getters in modules
-
Directly use: this.$store.getters. Module name. xxx
-
map auxiliary function:
computed: { ...mapGetters('Module name', ['xxx']), ...mapGetters('Module name',{'New name': 'xxx'}) }
How to use global mutations
-
Directly use: this.$store.commit('mutation name ', parameter)
-
map auxiliary function:
methods: { ...mapMutations(['mutation name']), ...mapMutations({'New name': 'mutation name'}) }
How to use changes (named: true) in modules
-
Directly use: this.$store.commit('module name / mutation name ', parameter)
-
map auxiliary function:
methods: { ...mapMutations('Module name', ['xxx']), ...mapMutations('Module name',{'New name': 'xxx'}) }
How to use global actions
-
Directly use: this.$store.dispatch('action name ', parameter)
-
map auxiliary function:
methods: { ...mapActions(['actions name']), ...mapActions({'New name': 'actions name'}) }
How to use actions (named: true) in modules
-
Direct use: this.$store.dispatch('module name / action name ', parameter)
-
map auxiliary function:
methods: { ...mapActions('Module name', ['xxx']), ...mapActions('Module name',{'New name': 'xxx'}) }