什么是vuex
vuex是一个专门为vue.js设计的集中式状态管理架构。状态?我把它理解为在data中的属性需要共享给其他vue组件使用的部分,就叫做状态。简单的说就是data中需要共用的属性。
什么时候使用vuex
在vue的组件化开发中,经常会遇到需要将当前组件的状态传递给其他组件。父子组件通信时,我们通常会采用 props + emit 这种方式。但当通信双方不是父子组件甚至压根不存在相关联系,或者一个状态需要共享给多个组件时,就会非常麻烦,数据也会相当难维护,这对我们开发来讲就很不友好。vuex 这个时候就很实用,虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建是一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
vuex状态管理
view ——> (dispatch) Action ——>(commit)Mutations ——> (Mutate)State ——> view
!["vuex"](/img/vuex/vuex_1.jpg)
vuex 初级实用版
count.vue内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46<template>
<div>
<h2>{{ msg }}</h2>
<hr>
<h3>{{ $store.state.count }} 通过computed赋值:{{ count }}</h3> //count通过computed对象定义
<div>
<button @click="$store.commit('plus')">+</button>
<button @click="addNumber">-</button> //通过methods定义方法函数
</div>
<div>以下通过action异步</div>
<div>
<button @click="$store.dispatch('addAction')">+</button>
<button @click="reduceAction">-</button> //通过通过methods定义方法函数
</div>
</div>
</template>
<script>
import store from '@/vuex/store'
export default {
data() {
return {
msg: 'Hello Vuex'
}
},
computed: { //count通过computed对象定义
count() {
return this.$store.state.count;
}
},
methods: {
addNumber() { //通过methods定义方法函数addNumber
return this.$store.commit("plus");
},
reduceAction() { //通过通过methods定义方法函数reduceAction
setTimeout(() => {
return this.$store.dispatch('minusAction')
},1000)
}
},
}
store
}
</script>
store.js文件内容:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const state = {
count: 1
}
const mutations = {
plus(state) {
state.count ++;
},
minus(state) {
state.count --;
}
}
const getters = {
addDual: state => state.count += 2
}
const actions = {
addAction({commit}) {
setTimeout(
() => { context.commit('plus')},3000);
},
minusAction({commit}) {
setTimeout(
() => { context.commit('minus')},3000);
}
}
modules: {
a: modulesA
}
export default new Vuex.Store({
state,
mutations,
getters,
actions
})
vuex 包含有五个基本的对象:
state:存储状态。也就是变量;组件调用方式:$store.state.count,在组件中也可以通过计算属性computed直接赋值:
1
2
3
4
5computed: {
count() {
return this.$store.state.count;
}
}getters:派生状态。也就是set、get中的get,有两个可选参数:state、getters分别可以获取state中的变量和其他的getters。组件调用方式:$store.getters.addDual()。就和vue的computed差不多:
1
2
3
4
5
6// 通过getters每次累加2
computed: {
addDual() {
return this.$store.state.count += 2;
}
}mutations:提交状态修改。也就是set、get中的set,这是vuex中唯一修改state的方式,但不支持异步操作。第一个参数默认是state。也可以向store.commit传入第二参数,也就是mutation的payload,组件调用方式:$store.commit(‘plus’)。和vue中的methods类似:
1
2
3
4
5methods: {
addNumber() {
return this.$store.commit("plus");
}
}actions:和mutations类似。不过actions支持异步操作。第一个参数默认是和store具有相同参数属性的对象。组件调用方式:store.dispatch(‘addAction’)。和vue中的methods类似:
1
2
3
4
5
6
7methods: {
reduceAction() {
setTimeout(() => {
return this.$store.dispatch('minusAction')
},1000)
}
}modules:store的子模块,内容就相当于是store的一个实例。调用方式和前面介绍的相似,只是要加上当前子模块名,如:$store.a.getters.xxx()。
辅助函数
在vue组件中使用时,我们通常会使用mapState、mapGetters、mapMutations、mapActions,然后就可以按照vue调用methods和computed的方式去调用这些变量或函数,示例如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import {mapState, mapGetters, mapMutations, mapActions} from 'vuex';
export default {
computed: {
...mapState([
count
]),
...mapGetters([
addDual
])
},
methods: {
...mapMutations({
addNumber
}),
...mapActions([
reduceAction
])
}
};
vue-cli项目中使用vuex的方式
1 | ├── index.html |
state.js示例:1
2
3
4
5const state = {
count: 1
}
export default state;
getters.js示例(我们一般使用getters来获取state的状态,而不是直接使用state):1
2
3export const addDual = (state) => {
return state.count += 2;
}
mutation-type.js示例(我们会将所有mutations的函数名放在这个文件里):1
2export const PLUS = 'PLUS';
export const MINUS = "MINUS"
mutations.js示例:1
2
3
4
5
6
7
8
9
10
11
12import {PLUS, MINUS} from './mutation-type';
import {
} from './mutation-types'
export default {
[PLUS] (state) {
state.count++
},
[MINUS] (state) {
state.count--
},
actions.js示例(异步操作、多个commit时):1
2
3
4
5
6
7
8
9
10
11
12
13import {PLUS, MINUS} './mutation-type';
export default {
plusAction({commit}) {
setTimeout(
() => {commit(PLUS)},3000);
},
minusAction({commit}) {
setTimeout(
() => { commit(MINUS)},3000);
},
};
modules–m1.js示例(如果不是很复杂的应用,一般来讲是不会分模块的):1
2
3
4
5
6export default {
state: {},
getters: {},
mutations: {},
actions: {}
};
index.js示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import vue from 'vue';
import vuex from 'vuex';
import state from './state';
import * as getters from './getters';
import mutations from './mutations';
import actions from './actions';
import m1 from './modules/m1';
import m2 from './modules/m2';
vue.use(vuex);
export default new vuex.Store({
state,
getters,
mutations,
actions,
modules: {
m1,
m2
},
最后将store实例挂载到main.js里面的vue上去就行了1
2
3
4
5
6
7import store from './store/index.js';
new Vue({
el: '#app',
store,
render: h => h(App)
});