前 言
刚接触Vue
的时候,组件之间通信真的是个令人头疼的事情,最开始还用过bus
,后来知道有个Vuex
这个东东,越来越喜欢,今天就做个整理。
正 文
- state
都叫状态管理了,首先肯定得有状态state
const state = {
loginState: false
...
}
他就是一个简单的对象,key-value
,然后我们要做的就是对这些状态进行操作(修改和读取)。
- getters
const getters = {
getLoginState({ loginState }) {
return loginState
}
}
顾名思义,就是获取对应的state,使用方法为:
let loginState = store.getters['getLoginState']
- mutations
const mutations = {
setLoginState(state, { loginState }) {
state.loginState = loginState
}
}
mutation
意思为“改变”,就是改变state
的值,通过commit
来实现:
store.commit('setLoginState', { loginState: true })
- actions
const actions = {
changeState({ commit }, payload) {
commit('setLoginState', payload)
}
}
action
意为“动作,行为”,它有以下规则:
-
action
不可以直接修改状态state
,它通过commit mutation
来间接的改变state
-
action
可以包含异步操作
使用dispatch
来调用action
:
store.dispatch('changeState', { loginState: true })
- modules
随着项目越来越庞大,store
可能会越来越臃肿,所以Vuex
提供了modules
方便管理,可以根据具体业务来划分模块。
如果login
和logout
都有一个state
为userId
,那么此时就需要一个namespaced
属性来区别这个userId
到底属于哪个模块:
const login = {
state: { ... },
getters: { ... },
mutations: { ... },
actions: { ... },
namespaced: true
}
const logout = {
state: { ... },
getters: { ... },
mutations: { ... },
actions: { ... },
namespaced: true
}
const store = new Vuex.Store({
modules: {
login,
logout
}
})
// getters和commit时,加上模块名
store.getters['login/userId']
store.commit('login/userId', 123456)
进阶
有时候我们多次从store拿数据时,会觉得很繁琐,别担心,vuex提供了辅助函数,即mapState,mapGetters,mapMutations以及mapActions。使用前需要引入它们:
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
- mapState,mapGetters
// mapState
mapState(['loginState'])
// 等价于
loginState() {
return this.$store.state['loginState']
}
// mapGetters
mapGetters(['loginState'])
// 等价于
loginState() {
return this.$store.getters['loginState']
}
这样我们就可以结合computed使用了
computed: {
mapState(['loginState'])
}
// 获取多个状态
computed: {
...mapState([
'loginState',
'loginInfo'
])
}
- mapMutations
methods: {
...mapMutations([
'setLoginState'
])
}
// 等价于
methods: {
setLoginState(payload) {
this.$store.commit('setLoginState', payload)
}
}
- mapActions
methods: {
...mapActions([
'changeState'
])
}
// 等价于
methods: {
changeState(payload) {
this.$store.dispatch('changeState', payload)
}
}
*需要注意的是,以数组为辅助函数的参数时,数组参数的每个成员必须和store中定义好的名称一一对应;如需使用别名,请使用对象参数,对象的key为我们设置的别名,value对应state里的变量名,如下:
computed: {
...mapState({
'state': 'loginState'
})
}
// 等价于
computed: {
state() {
return this.$store.getters['loginState']
}
}
应用场景
其实Vuex
的应用场景还是很多的,这里简单举个例子。
data () {
return {
isHorizontal: this.$store.getters[NS.MAIN.GET_IS_HORIZONTAL]
}
},
computed: {
isHorizontal () {
return this.$store.getters[NS.MAIN.GET_IS_HORIZONTAL]
}
}
这里是直接使用在了data
和computed
里。
在ts项目里,可以结合class
的get
方法使用,效果很好
export default class Demo extends Vue {
name: string = 'Demo'
type: string = this.$store.getters['getType']
get number(): number {
return this.$store.getters['getNumber']
}
mounted() {
console.log(this.type, this.number) // default type, default number
this.$store.commit('setType', 'new type')
this.$store.commit('setNumber', 1)
console.log(this.type, this.number) // default type, 1
}
}
另外还涉及到浅拷贝的问题,看例子:
export default class Demo extends Vue {
name: string = 'Demo'
mounted() {
let obj = this.$store.getters['getObj'] // {success: true}
obj.success = false
console.log(this.$store.getters['getObj']) // {success: false}
}
}