在 Vue 里面的中央状态管理器,用于改变数据和获取数据。Vuex 还能追踪所作的改变。
像这种管理数据的方式有很多
- 传值的方式,父组件往子组件传值
- eventBus 的方式
这两种方式共同的缺点是随着项目数据越来越多,文件会越来越复杂,不容易维护
同时也不能同追踪是谁来引发状态的改变源头
State
状态、数据
在 Vuex 通过 Vue.use(Vuex) 和 Vue.store 的选项注入到每个子组件中后,子组件能通过 this.$store 访问到 store
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
}
});
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
Getter
state 加工后的值,类似于Vue 中的 computed 计算属性的 get
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
getters:{
doubleCounter: (state, getters) => state.counter * 2
}
});
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.getters.doubleCounter
}
}
}
通过方法访问
可以通过让 getter 返回一个函数,来实现给 getter 传参。 store 里的数组进行查询时非常有用。
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
Mutations
用于改变状态,
而且操作通过 Vue Devtools 是有记录跟踪到的,但正因如此 Mutations 也只能做同步的操作,这样才能记录到正确的跟踪信息
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
getters:{
doubleCounter: (state, getters) => state.counter * 2
},
mutations:{
increment(state, payload) {
state.count += payload;
}
}
});
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.getters.doubleCounter
}
},
methods: {
increment(){
this.$store.commit('increment', 1)
}
}
}
Action
正因 Mutations 只能做同步的操作,但有些情况就是需要作异步的操作。这时就用于 Action
在 Mutations 上面加多一层,可以用于异步的 Action。当 Action 完成时,才提交 mutation 来改变状态。
所以 Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象
context.commit 提交一个 mutation
context.state / context.getters 获取 state / getters
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
getters:{
doubleCounter: (state, getters) => state.counter * 2
},
mutations:{
increment(state, payload) {
state.count += payload;
}
},
actions:{
increment: (context, payload) => {
context.commit('increment', payload)
}
}
});
辅助函数
当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。
mapState
生成一个 state 为基础的 computed 对象,参数接收数组或对象
import { mapState } from 'vuex';
export default {
computed: mapState(['count']),
// 相当于
computed: {
count () {
return this.$store.state.count
}
},
computed: mapState({counter: 'count'}), // 这样的 computed 对象可以给别名
computed: {
// 使用 rest 运算符混入 computed 对象中
...mapGetters({count: 'count'}),
// ... 这样就可以有其它 computed 对象属性了
}
}
mapGetters
生成一个 getters 为基础的 computed 对象,参数接收数组或对象
import { mapGetters } from 'vuex';
export default {
computed: mapGetters(['doubleCounter']),
// 相当于
computed: {
doubleCounter () {
return this.$store.getters.doubleCounter
}
},
computed: mapGetters({count: 'doubleCounter'}), // 这样的 computed 对象可以给别名
computed: {
// 使用 rest 运算符混入 computed 对象中
...mapGetters({count: 'doubleCounter'}),
// ... 这样就可以有其它 computed 对象属性了
}
}
mapMutations
映射 methods
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
mapActions
映射 methods
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
Module
将 store 分割成模块
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
命名空间
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应
namespaced: true 使其成为带命名空间的模块