在 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 使其成为带命名空间的模块
