状态

单一状态树

Vuex 使用 **单一状态树** - 也就是说,这个单一对象包含了所有应用程序级别的状态,并充当“唯一的事实来源”。这也意味着通常每个应用程序只有一个 store。单一状态树使定位特定状态变得简单,并允许我们轻松地为调试目的获取当前应用程序状态的快照。

单一状态树并不与模块化冲突 - 在后面的章节中,我们将讨论如何将状态和 mutation 拆分为子模块。

您在 Vuex 中存储的数据遵循与 Vue 实例中的 data 相同的规则,即状态对象必须是纯对象。**另请参阅:** Vue#data.

将 Vuex 状态获取到 Vue 组件中

那么,我们如何在 Vue 组件中显示 store 中的状态呢?由于 Vuex store 是响应式的,因此从 store 中“检索”状态的最简单方法是在 计算属性 中返回一些 store 状态。

// let's create a Counter component
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

每当 store.state.count 发生变化时,它都会导致计算属性重新计算,并触发相关的 DOM 更新。

但是,这种模式会导致组件依赖于全局 store 单例。在使用模块系统时,它需要在使用 store 状态的每个组件中导入 store,并且还需要在测试组件时进行模拟。

Vuex 通过 Vue 的插件系统将 store “注入”到从根组件到所有子组件中,并且将在这些组件上以 this.$store 的形式可用。让我们更新我们的 Counter 实现

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState 辅助函数

当组件需要使用多个 store 状态属性或 getter 时,声明所有这些计算属性可能会变得重复且冗长。为了解决这个问题,我们可以使用 mapState 辅助函数,它为我们生成计算 getter 函数,从而节省了一些按键操作。

// in full builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // arrow functions can make the code very succinct!
    count: state => state.count,

    // passing the string value 'count' is same as `state => state.count`
    countAlias: 'count',

    // to access local state with `this`, a normal function must be used
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

当映射的计算属性的名称与状态子树的名称相同时,我们也可以将字符串数组传递给 mapState

computed: mapState([
  // map this.count to store.state.count
  'count'
])

对象展开运算符

请注意,mapState 返回一个对象。我们如何将它与其他局部计算属性结合使用?通常,我们需要使用一个实用程序将多个对象合并为一个,以便我们可以将最终对象传递给 computed。但是,使用 对象展开运算符,我们可以大大简化语法。

computed: {
  localComputed () { /* ... */ },
  // mix this into the outer object with the object spread operator
  ...mapState({
    // ...
  })
}

组件仍然可以拥有局部状态

使用 Vuex 并不意味着您应该将 **所有** 状态都放入 Vuex 中。虽然将更多状态放入 Vuex 会使您的状态 mutation 更明确且可调试,但有时它也会使代码更冗长且间接。如果某个状态严格属于单个组件,那么将其保留为局部状态可能就足够了。您应该权衡利弊,并做出适合您的应用程序开发需求的决定。