Vuex的核心属性

VueX 是一个专门为 Vue.js 应用设计的状态管理构架,统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data )。

Vuex有5个核心属性

  1. state vuex存放的基本数据
  2. getters 从基本数据派生的数据(类似computed)
  3. mutations 提交更改数据的方法(类似methods) 提交修改用commit this.$store.commit(‘mutations方法名’,值)
  4. actions 和mutation一样,只用于存放异步方法 提交修改用dispatch this.$store.dispatch(‘actions方法名’,值)
  5. modules 模块化vuex

state

单一状态树

Vuex使用单一状态树,即用一个对象就包含了全部的状态数据。state作为构造器选项,定义了所有我们需要的基本状态参数。

在Vue组件中获得Vuex属性

  • 我们可以通过Vue的Computed获得Vuex的state,如下:
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

getters

getters接收state作为其第一个参数,接受其他 getters 作为第二个参数

const store = new Vuex.Store({
    state: {
        count:0
    },
    getters: {
        // 单个参数
        countDouble: function(state){
            return state.count * 2
        },
        // 两个参数
        countDoubleAndDouble: function(state, getters) {
            return getters.countDouble * 2
        }
    }
})

与state一样,我们也可以通过Vue的Computed获得Vuex的getters


const app = new Vue({
    //..
    store,
    computed: {
        count: function(){
            return this.$store.state.count
        },
        countDouble: function(){
            return this.$store.getters.countDouble
        },
        countDoubleAndDouble: function(){
            return this.$store.getters.countDoubleAndDouble
        }
    },
    //..

mutations

提交mutation是更改Vuex中的store中的状态的唯一方法。

mutation必须是同步的,如果要异步需要使用action。

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷(payload)作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。


const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    //无提交荷载
    increment(state) {
        state.count++
    },
    //提交荷载
    incrementN(state, obj) {
      state.count += obj.n
    }
  }
})

你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:


//无提交荷载
store.commit('increment')
//提交荷载
store.commit('incrementN', {
    n: 100
    })

对象风格的提交方式

我们也可以使用这样包含 type 属性的对象的提交方式


store.commit({
  type: 'incrementN',
  n: 10
})

actions

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

通常用来封装mutations或者异步提交mutations

我们用如下例子来解释actions:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      setInterval(function(){
        context.commit('increment')
      }, 1000)
    }
  }
})

注意:Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

分发actions

Action 通过 store.dispatch 方法触发:

store.dispatch('increment')

modules

使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。

为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:

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 的状态

模块的局部状态

对于模块内部的 mutationgetter,接收的第一个参数是模块的局部状态,对于模块内部的 getter,根节点状态会作为第三个参数:


const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // state 模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    },
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

同样,对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState:


const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum (context) {
      if ((context.state.count + context.rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

通常项目的目录