1.什么是Vuex?
Vuex是一个专门为Vue.js应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规则保证状态以一种可预测的方式发生变化.
上面图片中绿色虚线部分就代表的是Vuex的核心。
state:
其中state
相当于vue
实例中的data
,用来保存所有组件的公共数据。
mutations:
state
只能通过mutations
进行修改,不可以直接修改state
数据。
actions:
actions
类似于mutations
,不过actions
提交的是 mutations
,而不是直接变更状态。actions
中可以包含异步操作, mutations
中绝对不允许出现异步。
2.为什么要使用Vuex?
多个组件之间互相通信,会非常的繁琐,所以在多个组件共享数据的时候需要用到Vuex。
安装:
使用 npm:
import Vuex from 'vuex'
Vue.use( Vuex );
创建一个项目:
export default new Vuex.Store({
state: {
},
mutations: {
},
getters: {
},
actions: {
}
})
new Vue({
el: '#app',
store,
render: h => h(App)
})
3.Vuex的核心概念
1.state:
其中state
相当于vue
实例中的data
,用来保存所有组件的公共数据。
2.getters:
我将getters属性理解为所有组件的computed属性, 也就是计算属性. vuex的官方文档也是说到可以将getter理解为store的计算属性, getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
mapGetters 辅助函数:
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',// 把 `this.doneTodosCount` 映射为 `this.$store.getters.doneTodosCount`
'anotherGetter',
// ...
])
}
}
这样就可以在组件中 使用 this.doneTodosCount 直接调用store的getters中的doneTodosCount方法了
3.mutations:
我将mutaions理解为store中的methods, mutations对象中保存着更改数据的回调函数,该函数名官方规定叫type, 第一个参数是state, 第二参数是payload, 也就是自定义的参数.
调用mutations必须用store.commit()提交
store.commit('方法', 参数)
// 支持载荷和对象方式进行分发
// 以载荷形式分发
store.commit('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.commit({
type: 'incrementAsync',
amount: 10
})
Mutation 必须是同步函数
mapMutations 辅助函数:
mapMutations 辅助函数仅仅是将 store 中的 mutations 映射到局部计算属性:
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')`
})
}
}
4.actions:
actions 类似于 mutations,不同在于:
- actions提交的是mutations而不是直接变更状态
- actions中可以包含异步操作, mutations中绝对不允许出现异步
- actions中的回调函数的第一个参数是context, 是一个与store实例具有相同属性和方法的对象
一个简单的actions:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
实践中,我们会经常用到 ES2015 的 参数解构 来简化代码(特别是我们需要调用 commit
很多次的时候):
actions: {
increment ({ commit }) {
commit('increment')
}
}
调用actions必须用store.dispatch()触发(分发)
store.dispatch('方法', 参数)
// 支持载荷和对象方式进行分发
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
mapActions 辅助函数:
mapActions 辅助函数仅仅是将 store 中的 actions 映射到局部计算属性:
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')`
})
}
}
5.Modules:
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
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 的状态