官网地址
基本思想:
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性
以一个全局单例模式管理抽取出来的组件共享状态
使用
1 | Vue.use(Vuex) //会调用install,在beforeMount声明周期进行初始化工作 |
state
具体变量声明对象,存放每个具体的公共变量
声明1
2
3
4
5const store = new Vuex.Store({
state: {
count: 0
},
)
在vue中使用—访问1
this.$store.state.count
getter
相当与vue的计算属性
访问声明的属性时,执行对应的函数,拿到的值为函数返回的值
如果函数返回另一个函数,则可以调用返回的函数去实现相应的功能
适用于多个组件共享一个同样处理逻辑的函数
getter 的返回值会根据它的依赖被缓存起来
且只有当它的依赖值发生了改变才会被重新计算
Getter 接受 state 作为其第一个参数
声明1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
// 受其他 getter 作为第二个参数,调用其他getter方法
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
})
在vue中使用—访问1
2
3this.$store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
this.$store.getters.doneTodosCount // -> 1
this.$store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
Mutation
存储同步改变state保存值的方法
声明1
2
3
4
5
6
7
8
9
10const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state, payload) { //payload即调用时传递进来的参数
state.count += payload.amount
}
}
})
在vue中使用—调用1
2
3this.$store.commit('increment', {
amount: 10
})
注意事项
1.提前在 store 中初始化好所有所需属性。
2.当需要在对象上添加新属性时,应该使用 Vue.set或者以新对象替换老对象
映射辅助函数mapMutations
Action
存储异步改变state保存值的方法
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。但他不是 store 实例本身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
40const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
},
incrementAsync ({ commit }) { //结构仅拿到contex里面的commit
setTimeout(() => {
commit('increment')
}, 1000)
},
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
},
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
},
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
}
})
在VUE中使用—调用1
2
3
4
5
6
7
8
9
10
11this.$store.dispatch('incrementAsync', { //作为第二个参数传递action
amount: 10
})
this.$store.dispatch('actionA').then(() => {
// ...
})
this.$store.dispatch('actionB').then(() => {
// ...
})
Modules
声明多个store配置对象,每个作为一个模块
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
套嵌条件下,state 会处理成树状结构进行访问,但要进行更改操作时,
如果有子模块没有进行命名空间设置,但又包含跟全局状态相同处理名称的 mutation 或 action
则在调用时,都会执行
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。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
46let moduleA = {
namespaced: true,
state(){
return{
counta: 0, //分别在模块b和全局下被使用,直接返回对象会通过引用被共享,防止模块间数据污染,使用函数,每次生成新对象,原理同vue的data
}
},
mutations: { // this.$store.commit('b/aa/increment') 仅触发模块b下面的aa子模块
increment (state) { //this.$store.commit('a/increment') 仅触发全局的模块a 对应的子模块
state.counta++
},
incrementaaa (state) { //在被引用时,套嵌层如果都没有namespaced: true,可以直接用this.$store.commit('incrementaaa')调用进行更改
state.counta++
}
}
}
let moduleB = {
namespaced: true,
state: {
countb: 0,//this.$store.state.b.countb
},
mutations: {
increment (state) { //如果不加namespaced,执行this.$store.commit('increment'),会同时执行
state.countb++
}
},
modules: {//如果moduleB不加namespaced,aa可以访问数据但不能调用this.$store.commit('b/aa/increment')进行更改
aa: moduleA,//this.$store.state.b.aa.counta
}
}
// vuex相关代码
const store = new Vuex.Store({
state: {
count: 0, //this.$store.state.count
},
mutations: {
increment (state) { //this.$store.commit('increment') 子模块有相同函数时,都会触发执行
state.count++
}
},
modules: {
a: moduleA, //this.$store.state.a.counta
b: moduleB //this.$store.state.b.countb
}
})
小结
namespaced: true相当于子模块的隔离层,
如果设置了,外界不能直接通过mutations里面的函数名进行commit调用,
即当调用相同函数名时,可以防止一起被调用
如果没有设置,则当调用相同类型commit时,会一起被调用
1.对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
2.带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
3.对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26const moduleA = {
namespaced: true,
state: { count: 0 },
mutations: {
increment (state) {
// 这里的 `state` 对象是模块的局部状态
state.count++
}
},
getters: {
doubleCount (state) {
return state.count * 2
}
},
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
更新补充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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64let moduleA = {
namespaced: true,
state(){
return{
counta: 0, //分别在模块b和全局下被使用,直接返回对象会通过引用被共享,防止模块间数据污染,使用函数,每次生成新对象,原理同vue的data
}
},
getters:{
getCount(...args){ //this.$store.getters['b/aa/getCount'] 作为b子模块时
console.log(args)
return 'this is a getter~~~~~'
}
},
mutations: { // this.$store.commit('b/aa/increment') 仅触发模块b下面的aa子模块
increment (state) { //this.$store.commit('a/increment') 仅触发全局的模块a 对应的子模块
state.counta++
},
incrementaaa (state) { //在被引用时,套嵌层如果都没有namespaced: true,可以直接用this.$store.commit('incrementaaa')调用进行更改
state.counta++
}
}
}
let moduleB = {
namespaced: true,
state: {
countb: 0,//this.$store.state.b.countb
},
getters:{
getCount(...args){ //this.$store.getters['b/getCount'] 因为设置了namespaced所以可以重名
console.log(args)
return 'this is a getter~~~~~'
}
},
mutations: {
increment (state) { //如果不加namespaced,执行this.$store.commit('increment'),会同时执行
state.countb++
}
},
modules: {//如果moduleB不加namespaced,aa可以访问数据但不能调用this.$store.commit('b/aa/increment')进行更改
aa: moduleA,//this.$store.state.b.aa.counta
}
}
// vuex相关代码
const store = new Vuex.Store({
state: {
count: 0, //this.$store.state.count
},
getters:{
getCount(...args){ //this.$store.getters.getCount
console.log(args)
return 'this is a getter'
}
},
mutations: {
increment (state) { //this.$store.commit('increment') 子模块有相同函数时,都会触发执行
state.count++
}
},
modules: {
a: moduleA, //this.$store.state.a.counta
b: moduleB //this.$store.state.b.countb
}
})