获取器

有时我们可能需要根据存储状态计算派生状态,例如过滤项目列表并对其进行计数

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

如果多个组件需要使用它,我们必须要么复制该函数,要么将其提取到一个共享的辅助函数中并在多个地方导入它 - 这两种方法都不理想。

Vuex 允许我们在存储中定义“获取器”。您可以将它们视为存储的计算属性。

警告

从 Vue 3.0 开始,获取器的结果不会像计算属性那样被缓存。这是一个已知问题,需要发布 Vue 3.1 才能解决。您可以在PR #1878中了解更多信息。

获取器将接收状态作为其第一个参数

const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos (state) {
      return state.todos.filter(todo => todo.done)
    }
  }
})

属性式访问

获取器将暴露在store.getters对象上,您可以像访问属性一样访问值

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

获取器还将接收其他获取器作为其第二个参数

getters: {
  // ...
  doneTodosCount (state, getters) {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

我们现在可以轻松地在任何组件中使用它

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}

请注意,作为属性访问的获取器将在 Vue 的响应式系统中被缓存。

方法式访问

您还可以通过返回一个函数来向获取器传递参数。当您想要查询存储中的数组时,这特别有用

getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

请注意,通过方法访问的获取器将在每次调用时运行,并且结果不会被缓存。

mapGetters 辅助函数

mapGetters 辅助函数只是将存储获取器映射到本地计算属性

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    // mix the getters into computed with object spread operator
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

如果您想将获取器映射到不同的名称,请使用对象

...mapGetters({
  // map `this.doneCount` to `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})