Vuex

状态管理工具

vuex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})

State

用来存储公共状态

1
2
3
state: {
count: 0
}

组件直接调用 state 中的数据

1
this.$store.state.count

也可以再计算属性中使用

1
2
3
4
5
computed: {
count() {
return this.$store.state.count
}
}

辅助函数 - mapState

将 state 中的数据映射到组件的计算属性中

1
2
3
4
5
6
7
8
import { mapState } form 'vuex'

export default {
computed: {
/* 拓展运算符 */
...mapState(['count'])
}
}

mapState()返回值为对象


1
2
3
4
5
6
7
import { mapState } form 'vuex'

export default {
computed: {
...mapState({myCount: 'count'})
}
}

mapState()除了接收数组以外,还可以接收对象

用于给 state 中的数据取别名

Getters

相当于store的计算属性,只有依赖值发生改变就会重新计算

1
2
3
getters: {
num: state => parseInt(state.count)
}

组件中直接使用 getters 中的数据

1
this.$store.getters.num

也可以再计算属性中使用

1
2
3
4
5
computed: {
num() {
return this.$store.getters.num
}
}

辅助函数 - mapGetters

1
2
3
4
5
6
7
8
import { mapGetters } form 'vuex'

export default {
computed: {
/* 拓展运算符 */
...mapGetters(['num'])
}
}

Mutations

操作 State 中的数据(只能执行同步代码),目的是形成数据快照

数据快照:一次 mutations 执行,立即生成一种视图状态

1
2
3
4
5
6
7
8
state: {
count: 0
},
mutations: {
addCount(state, payload) {
state.count += payload
}
}

参数:

  • state:就是 Vuex 中的 state 对象
  • payload:载荷(可以是任何形式的数据)

组件直接调用 mutations 方法

1
2
3
4
5
methods: {
addCount() {
this.$store.commit('addCount', 1)
}
}

参数:

  • 第一个参数:就是 mutations 方法名
  • 第二个参数:就是载荷

使用对象风格传参

1
2
3
4
5
6
7
8
methods: {
addCount() {
this.$store.commit({
type: 'addCount',
num: 1
})
}
}
1
2
3
4
5
6
7
8
state: {
count: 0
},
mutations: {
addCount(state, payload) {
state.count += payload.num
}
}

使用对象风格传参,就是将整个对象作为参数传给 payload

辅助函数 - mapMutations

将 mutations 中的方法映射在组件的 methods 中

1
2
3
4
5
6
7
import { mapMutations } form 'vuex'

export default {
methods: {
...mapMutations(['addCount'])
}
}

使用辅助函数调用 mutations 方法时,如果需要传入载荷,则需要在组件中调用方法时传入参数

1
<button @click="addCount(1)"></button>

1
2
3
4
5
6
7
import { mapMutations } form 'vuex'

export default {
methods: {
...mapMutations({add: 'addCount'})
}
}

mapMutations 函数同样支持对象格式传参,给方法取别名

Actions

执行异步操作

actions 提交的是 mutations 方法,而不是改变数据

1
2
3
4
5
actions: {
addCount(context, params) {
context.commit('addCount', payload)
}
}

参数:

  • context:==与 store 相同属性和方法的对象==
  • payload:载荷

组件直接调用 actions 方法

1
this.$store.dispatch('addCount', 1)

使用对象风格传参

1
2
3
4
5
6
7
8
methods: {
addCount() {
this.$store.dispatch({
type: 'addCount',
num: 1
})
}
}
1
2
3
4
5
6
7
8
state: {
count: 0
},
actions: {
addCount(context, payload) {
context.commit('addCount', payload.num)
}
}

使用对象风格传参,就是将整个对象作为参数传给 payload

辅助函数 - mapActions

1
2
3
4
5
6
7
import { mapActions } form 'vuex'

export default {
methods: {
...mapActions(['addCount'])
}
}

传参方式与 mapMutations 函数相同


1
2
3
4
5
6
7
import { mapActions } form 'vuex'

export default {
methods: {
...mapActions({add: 'addCount'})
}
}

mapActions 函数同样支持对象格式传参,给方法取别名

模块化

1
2
3
4
5
6
7
store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── user.js # 用户模块
└── setting.js # 设置模块

modules

将 store 拆除多个模块,每个模块都有自己的 state、mutation、action、getter

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
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const user = {
state: {
},
getters: {
},
mutations: {
},
actions: {
}
}

export default new Vuex.Store({
modules: {
user,
setting: {
state: {
},
getters: {
},
mutations: {
},
actions: {
}
}
}
})

./store/modules/moduleA.js

1
2
3
4
5
6
7
8
9
10
11
12
const user = {
state: {
},
getters: {
},
mutations: {
},
actions: {
}
}

export default user

./store/index.js

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'

Vue.use(Vuex)

export default new Vuex.Store({
modules: {
user
}
})

可以将每个 module 拆成一个文件,单独编写,提高独立性

最后由 ./store/index.js 统一导入、抛出

命名空间

namespaced

默认情况下,模块下的 state、getters、actions、mutations 都是全局命名空间

也就是在全局都可以直接调用


如果需要实现高封闭性,这需要设置命名空间namespaced: true

1
2
3
4
5
6
7
8
9
10
11
user: {
namespaced: true,
state: {
},
getters: {
},
mutations: {
},
actions: {
}
}

这样外部就不能直接调用 user 模块内部的 mutations、actions、getters

调用带命名空间的模块

  1. 带模块名调用
1
this.$store.commit(['user/changeInfo'])
  1. 辅助函数带模块名调用
1
2
3
4
5
6
7
8
9
10
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations(['user/changeInfo'])

change() {
this['user/changeInfo']()
}
}
}
  1. createNamespacedHelpers
1
2
3
4
5
6
7
8
9
import { createNamespacedHelpers } from 'vuex'

const { mapMutations } = createNamespacedHelpers('user')

export default {
methods: {
...mapMutations(['changeInfo'])
}
}