1, Preface
I've been reviewing vue Family bucket , It feels more profound to see it again , So make a special record ( this paper vuex Version is v3.x).
2,Vuex What is it?
Vuex It's for Vue.js State management mode of development . It uses centralized storage , Manage the state of all components , And the corresponding rules ensure that the state changes in a predictable way ( My understanding is that global variables ).
3,5 Large attribute description
state
object type , Similar to the example data attribute , Storing data
getters
object type , Calculation properties similar to instances computed
mutations
object type , Similar to the example methods, But you can't handle asynchronous methods
actions
object type , Similar to the example methods, Can handle asynchronous methods
modules
object type , When state When there is a lot of content , Split into small modules through this attribute , Each module has its own state、mutation、action、getter
4,state
Stored in state
Data in and Vue
In the instance data
Follow the same rules , It must be a pure object .
4.1 Direct access
this.$store.state.xxx
4.1 Use mapState mapping
<template>
<div id="communication">
<p> Count :{{ getCount }}</p>
<p> School :{{ getSchool(' I am a parameter ') }}</p>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Vuex',
data() {
return {
date: 1998
}
},
computed: {
...mapState({
// mapState By default the state When the first parameter comes in
getCount: state => state.count,
getSchool(state) {
return (val) => {
return state.school + val + this.date
}
}
})
},
mounted() {
// Direct value
console.log(this.$store.state.count)
}
}
</script>
5,getters
getter
The return value of is cached according to its dependency , And only when its dependency value changes will it be recalculated , And accept by default state
As its first parameter , You can also accept other getter
As the second parameter ( Here's an example )
5.1 First in vuex In the definition of getters
export default new Vuex.Store({
state: {
count: 0,
school: ' Tsinghua University '
},
getters: {
// Return to the processed state value
getValue(state) {
return state.count + '!'
},
// Returns the call itself getters After processing the state value
getGetters(state, getters) {
return state.school + getters.getValue
},
// Accept the value after external parameter transfer ( When accessed through methods , Every time I make a call , Results are not cached )
getParam(state) {
return (param) => {
return state.school + param
}
}
},
mutations: {},
actions: {},
modules: {}
})
5.2 Get value directly
// Value
console.log(this.$store.getters.getGetters)
// Pass parameter value
console.log(this.$store.getters.getParam('param'))
5.3 Use mapGetters mapping
<template>
<div id="communication">
<p> Count :{{ getGetters }}</p>
<p> School :{{ getParam(date) }}</p>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'Vuex',
data() {
return {
date: 1998
}
},
computed: {
...mapGetters([
'getGetters',
'getParam'
])
},
mounted() {
// Direct value
console.log(this.$store.getters.getGetters)
console.log(this.getParam(this.date))
}
}
</script>
6,Mutation
By calling this.$store.commit('xxx')
, call mutation
The method in , change store
The value in
6.1, First in mutations Registered events in
export default new Vuex.Store({
state: {
count: 0,
school: ' Tsinghua University '
},
getters: {},
mutations: {
// Default state As the first parameter
handleAdd(state) {
state.count++
},
// Accept the transmission of reference
handleChange(state, value) {
state.school = value
}
},
actions: {},
modules: {}
})
6.2, Invoke method in component commit Modified value
<template>
<div id="communication">
<p> Count :{{ count }}</p>
<el-button @click="handleStoreAdd"> increase </el-button>
<el-button @click="handleStoreChange"> The ginseng </el-button>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Vuex',
data() {
return {
school: ' Wuhan University '
}
},
computed: {
...mapState([
'count'
])
},
methods: {
// Call modify
handleStoreAdd() {
this.$store.commit('handleAdd')
},
// Pass parameter modification
handleStoreChange() {
this.$store.commit('handleChange', this.school)
}
}
}
</script>
6.3, Use constants to define method names
New file mutation-types.js
, Constants that define method names , And export
export const ADD_COUNT = 'ADD_COUNT'
export const CHANGE = 'CHANGE'
stay store in
import Vue from 'vue'
import Vuex from 'vuex'
import * as MT from './mutation-types'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
school: ' Tsinghua University '
},
getters: {},
mutations: {
// Default state As the first parameter
[MT.ADD_COUNT](state) {
state.count++
},
// Accept the transmission of reference
[MT.CHANGE](state, value) {
state.school = value
}
},
actions: {},
modules: {}
})
In components
<template>
<div id="communication">
<p> Count :{{ count }}</p>
<el-button @click="handleStoreAdd"> increase </el-button>
<el-button @click="handleStoreChange"> The ginseng </el-button>
</div>
</template>
<script>
import { mapState } from 'vuex'
import * as MT from '../../store/mutation-types'
export default {
name: 'Vuex',
data() {
return {
school: ' Wuhan University '
}
},
computed: {
...mapState([
'count'
])
},
methods: {
// Call modify
handleStoreAdd() {
this.$store.commit(MT.ADD_COUNT)
},
// Pass parameter modification
handleStoreChange() {
this.$store.commit(MT.CHANGE, this.school)
}
}
}
</script>
6.4, Use mapMutations mapping
<template>
<div id="communication">
<p> Count :{{ count }}</p>
<p> Count :{{ school }}</p>
<el-button @click="handleStoreAdd"> increase </el-button>
<el-button @click="handleStoreChange(schools)"> The ginseng </el-button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import * as MT from '../../store/mutation-types'
export default {
name: 'Vuex',
data() {
return {
schools: ' Wuhan University '
}
},
computed: {
...mapState([
'count',
'school'
])
},
methods: {
...mapMutations({
handleStoreAdd: MT.ADD_COUNT,
handleStoreChange: MT.CHANGE
})
}
}
</script>
7,Action
Be careful ,Action
Is submitted mutation
, Instead of changing the state directly , And can contain any asynchronous operation
7.1, stay store In the definition of
import Vue from 'vue'
import Vuex from 'vuex'
import * as MT from './mutation-types'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
school: ' Tsinghua University '
},
getters: {},
mutations: {
// Default state As the first parameter
[MT.ADD_COUNT](state) {
state.count++
},
// Accept the transmission of reference
[MT.CHANGE](state, value) {
state.school = value
}
},
actions: {
add(context) {
context.commit(MT.ADD_COUNT)
}
},
modules: {}
})
7.2, Use in components
<template>
<div id="communication">
<p> Count :{{ count }}</p>
<el-button @click="actionAdd"> increase </el-button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import * as MT from '../../store/mutation-types'
export default {
name: 'Vuex',
data() {
return {
schools: ' Wuhan University '
}
},
computed: {
...mapState([
'count',
'school'
])
},
methods: {
...mapMutations({
handleStoreAdd: MT.ADD_COUNT,
handleStoreChange: MT.CHANGE
}),
// call action Methods , Need to use $store.dispatch
actionAdd() {
this.$store.dispatch('add')
}
}
}
</script>
7.3, Use mapActions mapping
import { mapActions } from 'vuex'
methods: {
...mapActions([
'moduleFn'
])
}
perhaps
import { mapActions } from 'vuex'
methods: {
...mapActions([
fn: 'moduleFn'
])
}
7.4, Simplify writing
Action
Accept a relationship with store
The instance has the same methods and properties context
Parameter object , So you can call context.commit
To submit a mutation
, Or by context.state
and context.getters
To get state
and getters
, utilize ES6
Deconstruction of , It can be simplified .
actions: {
add({ commit, state }) {
commit(MT.CHANGE, state.school)
}
}
7.5, Perform asynchronous operations
stay vuex in
import Vue from 'vue'
import Vuex from 'vuex'
import * as MT from './mutation-types'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
getters: {},
mutations: {
// Default state As the first parameter
[MT.ADD_COUNT](state) {
state.count++
}
},
actions: {
add({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit(MT.ADD_COUNT)
resolve()
}, 1000)
})
}
},
modules: {}
})
Use in components async / await
perhaps then / catch
Deal with asynchronous
<template>
<div id="communication">
<p> Count :{{ count }}</p>
<el-button @click="actionAdd"> increase </el-button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import * as MT from '../../store/mutation-types'
export default {
name: 'Vuex',
data() {
return {
schools: ' Wuhan University '
}
},
computed: {
...mapState([
'count',
'school'
])
},
methods: {
...mapMutations({
handleStoreAdd: MT.ADD_COUNT,
handleStoreChange: MT.CHANGE
}),
// call action Methods , Need to use $store.dispatch
async actionAdd() {
await this.$store.dispatch('add')
console.log(1998)
}
}
}
</script>
8,Modules
When the application becomes very complex ,store
Objects can become quite bloated . At this time, you can store
Split into modules , Each module has its own state
、mutation
、action
、getter
、 Even nested submodules , Divide from top to bottom in the same way .
8.1, preparation
stay store New under the directory Modules
Folder , stay Modules
New in folder modulesA.js
,modulesB.js
, Here's the picture
stay modulesA.js Write the of local modules in state
、mutation
、action
、getter
, And export
const moduleA = {
state: () => ({
a: ' I am a moduleA'
}),
getters: {},
mutations: {},
actions: {}
}
export default moduleA
And then in store
Of index.js
Introduction in , And throw it in modules
In the object
import Vue from 'vue'
import Vuex from 'vuex'
import * as MT from './mutation-types'
import moduleA from './modules/moduleA'
import moduleB from './modules/moduleB'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
getters: {},
mutations: {},
actions: {},
modules: {
moduleA,
moduleB
}
})
8.2, Use modules Of modules injected in state
Use... Directly in components
this.$store.state.moduleA.xxx
Use in components mapState
mapping
<span>{{ moduleA.xxx }}</span>
import { mapState } from 'vuex'
computed: {
...mapState([
'moduleA'
])
}
8.3, Use modules Of the injection module getters
Use... Directly in components
this.$store.getters.getModuleA
Use in components mapState
mapping
<p>{{ getModuleA }}</p>
import { mapGetters } from 'vuex'
computed: {
...mapGetters([
'getModuleA'
])
}
Internal to the module getter
, Accepted parameters state
and getters
Is the local state object of the module , The state of the root node is the third parameter rootState
Exposed
const moduleA = {
getters: {
getModuleA(state, getters, rootState) {
return state.xxx + '---' + rootState.xxx
}
}
}
If you need to take parameters
const moduleA = {
getters: {
getModuleA(state, getters, rootState) {
return (value) => {
return state.a + '---' + value
}
}
}
}
8.4, Use modules Of the injection module mutations
Use... Directly in components
this.$store.commit('setModuleA') || this.$store.commit('setModuleA', ' Parameters ')
Use in components mapMutations
mapping
import { mapMutations } from 'vuex'
methods: {
...mapMutations([
openFn: 'setModuleA'
])
}
Internal to the module mutations
, First parameter accepted by default state
Is the local state object of the module
const moduleA = {
mutations: {
setModuleA(state) {
state.xxx += 'xxx'
}
}
}
If you need to take parameters
const moduleA = {
mutations: {
setModuleA(state, value) {
state.xxx += value
}
}
}
8.5, Use modules Of the injection module actions
Use... Directly in components
this.$store.dispatch('xxx')
Use in components mapActions
mapping
import { mapActions } from 'vuex'
methods: {
...mapActions([
'moduleA'
])
}
Or rename
import { mapActions } from 'vuex'
methods: {
...mapActions({
fn: 'moduleA'
})
}
For internal action
, Local state pass context.state
Exposed , The root node status is context.rootState
const moduleA = {
// ...
actions: {
fn ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
8.6, Namespace
By default , Internal to the module action
、mutation
and getter
Is registered in the global namespace , This allows multiple modules to be on the same mutation
or action
A response . If you want the module to have higher encapsulation and reusability , You can add... To the module namespaced: true
To make it a module with a namespace . When the module is registered , All of it getter
、action
And mutation
Will automatically adjust the name according to the path registered by the module .
8.6.1, Use
First in the module moduleB.js
Add namespaced: true
const moduleB = {
namespaced: true,
state: () => ({
b: ' I am a moduleB'
}),
mutations: {},
actions: {},
getters: {}
}
export default moduleB
stay store
Of index.js
in
import moduleA from './modules/moduleA'
import moduleB from './modules/moduleB'
export default new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {
moduleA,
moduleB
}
})
If you use namespaces in components , You need to bring the space name ,mapState
, mapGetters
, mapMutations
,mapActions
Use the same .
<script>
import { mapState, mapGetters, mapMutations } from 'vuex'
export default {
name: 'Vuex',
data() {
return {}
},
computed: {
// What's injected here is moduleA Module data
...mapState('moduleA', [
'a'
]),
// Need injection moduleB modular , Just write another
...mapState('moduleB', [
'b'
])
},
mounted() {
// Use it directly
console.log(this.$store.state.moduleA.a)
console.log(this.$store.state.moduleB.b)
},
methods: {}
}
</script>
8.6.2 , Access global content within a module with a namespace
If you want to use global state
and getter
,rootState
and rootGetters
Will be passed in as the third and fourth parameters getter
, Also through context
Object's properties passed in action
. If you need to distribute within a global namespace action
Or submit mutation
, take { root: true }
As the third parameter to dispatch
or commit
that will do
const moduleA = {
namespaced: true,
state: () => ({
a: ' I am a moduleA'
}),
getters: {
getModuleA(state, getters, rootState, rootGetters) {
// Using the global namespace state or getters
return state.a + rootState.count
}
},
mutations: {
setModuleA(state) {
console.log(state.a)
}
},
actions: {
addM({ state, commit, dispatch, rootState, rootGetters }) {
console.log(rootState)
console.log(rootGetters)
// Call the method of the global namespace
dispatch('rootFunction', null, { root: true })
}
}
}
export default moduleA
8.6.3, Register the global... In the module with namespace action
Register the global... In the module with namespace action
, Need to add root: true
, And will the action
The definition of is in the function handler
in , among ,handler The first parameter of namespacedContext
Namely action
Medium Context
Parameters
const moduleA = {
namespaced: true,
state: () => ({
a: ' I am a moduleA'
}),
getters: {},
mutations: {},
actions: {
rootFn: {
root: true,
handler(namespacedContext, param) {
console.log(namespacedContext.state)
}
}
}
}
export default moduleA
If you read it and find it helpful , I am a @ Peng Duoduo , welcome give the thumbs-up Focus on Comment on ;END
The articles
Personal home page