State management VueX
Introduction to VueX
A brief introduction to VueX
- For componentized development, the state of a large application often spans multiple components. It is very troublesome to transfer state between multi-layer nested parent-child components, and Vue does not provide a way for sibling components to directly share data.
- Based on this problem, many frameworks provide solutions - use a global state manager to hand over all decentralized shared data to the state manager for safekeeping, and Vue is no exception.
- Vuex is a state management library specially developed for Vue.js applications, which uses centralized storage to manage the state of all components of the application.
- Simply put, Vuex is used to manage data scattered in various components of Vue.
- VueX installation: npm install vuex@next (install the latest version)
state management
- Vuex is not necessary for use in more complex website development.
- The core of every Vuex application is a store (the unified instance in vuex, the global object, and the data to be shared by all components can be stored inside the store, maintained and managed by it), which is different from ordinary global objects. Based on the characteristics of Vue data and view binding, when the state in the store changes, the view bound to it will also be re-rendered (the store is bound to the view ) .
- The state in the store is not allowed to be modified directly. The only way to change the state in the store is to explicitly submit (commit) the mutation, which allows us to easily track each state change (easy to maintain).
- In large and complex applications, if state changes cannot be effectively tracked, it will cause great trouble to understand and maintain the code.
- There are 5 important concepts in Vuex: State, Getter, Mutation, Action, Module.
If there is an asynchronous request, the Action is triggered through Dispatch, and the Action submits the Mutation to finally modify the data in the State; if there is no asynchronous operation, the component can also directly submit the Mutation to modify the value in the State.
Introduction to the use process of 5 important concepts in Vuex:
The following code is based on vue3, namely vuex4- State
State is used to maintain the state of all application layers and ensure that the application has only one data source.
In components, you can directly use this.$store.state.count to access data, or use the mapState auxiliary function to map it first
- Getter
Getter maintains some states derived from State, and these states change with the state of State (for example, State stores some to-do items, if completed is true, not completed is false, in this interface you may want to display all completed ones, or display all unfinished ones). In components, you can use this.$store.getters.doneTodos directly, or use the mapGetters auxiliary function to map it first, the code is as follows
:
- Mutation
Mutation provides methods to modify the State state.
In the component, you can directly use store.commit to submit the mutation
, or use the mapMutation auxiliary function to map it first
- Action
-
Only some synchronous operations can be done in Mutation. In order to track the state changes, if it is some asynchronous operation, use Action
-
Action is similar to Mutation, the difference is that: Action cannot directly modify the state, but can only be modified by submitting mutation, and Action can contain asynchronous operations.
-
Action is also defined in the method, the parameter is context (context object), instead of directly modifying the state, but submitting mutation. (For example, the data obtained by the network request needs to update the data in the State, and use the context to submit the mutation, and then indirectly modify the data in the State. The reason for this design is to record the changes in the State in the Action)
In the component, you can directly use this.$store.dispatch('xxx') to distribute the action, or use the mapActions auxiliary function to map it first
- State
VueX installation and use
VueX installation
Method 1 :
Select the vuex module to install when creating a vue project
Method 2 :
Use npm install to install
vue2: npm install vuex@3
vue3: npm install vuex@4
VueX uses
VueX uses about State
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
export default store
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App)
}).$mount('#app')
HelloWorld.vue
<template>
<div class="hello">
{
{ this.$store.state.count }}
<button @click="add">+1</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
methods:{
add(){
// this.$store.state.count = this.$store.state.count +1
this.$store.commit("increment")
}
}
}
</script>
HelloWorld.vue is easier to write
or
use the mapState helper function
to import in the components that need to be used:
import {
mapState } from 'vuex'
Modify the computed part (the following three methods are available):
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
We can also pass an array of strings to mapState when the name of the mapped computed property is the same as the name of the child node of the state.
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
VueX uses About Getter
src/store/index.js
uses mapGetters, code example:
HelloWorld.vue
<template>
<div class="hello">
<!-- {
{ this.$store.state.count }} -->
{
{ count }}
<button @click="add">+1</button>
<!-- Getter -->
<ul>
<li v-for="todo in doneTodos" :key="todo.id">{
{ todo.text }}</li>
</ul>
</div>
</template>
<script>
import {
mapState,mapGetters } from 'vuex'
export default {
name: 'HelloWorld',
//mapState与mapGetters同时使用
computed:{
...mapState([
'count','todos'
]),
...mapGetters([
'doneTodos'
])
},
methods:{
add(){
// this.$store.state.count = this.$store.state.count +1
this.$store.commit("increment")
}
}
}
</script>
VueX uses about Mutation
Additional parameters can be passed to store.commit, that is, the payload of the mutation:
src/store/index.js
mutations: {
// increment(state) {
// state.count++
// }
increment(state, n) {
state.count += n
}
},
HelloWorld.vue
methods:{
add(){
// this.$store.state.count = this.$store.state.count +1
this.$store.commit("increment",2)
}
}
You can use this.$store.commit('xxx') in the component to submit the mutation, or use the mapMutations auxiliary function to map the methods in the component to the store.commit call (need to inject the store at the root node).
import {
mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
VueX uses about Action
The reason to abstract Action is to record the state changes of asynchronous data
Register a simple Action
src/store/index.js
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Dispatch Action
Action is triggered by store.dispatch method:
store.dispatch('increment')
Distribute Actions in Components
Use this.$store.dispatch('xxx') to distribute actions in components, or use the mapActions auxiliary function to map component methods to store.dispatch calls (the store needs to be injected into the root node first):
HelloWorld.vue
import {
mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
VueX uses about Module
If the application data is particularly large, vue allows split modules.
Vuex allows us to split the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules—separated in the same way from top to bottom:
const moduleA = {
state: () => ({
... }),
mutations: {
... },
actions: {
... },
getters: {
... }
}
const moduleB = {
state: () => ({
... }),
mutations: {
... },
actions: {
... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态