Às vezes, talvez precisemos calcular o estado derivado com base no estado do store, por exemplo, filtrar através de uma lista de itens e contá-los:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
Se mais do que um componente precisa fazer uso disso, temos que duplicar a função, ou extraí-lo em um auxiliar compartilhado e importá-lo em vários lugares - ambos são menos do que o ideal.
O Vuex nos permite definir getters no store. Você pode pensar neles como dados computados para os stores. Como os dados computados, o resultado de um getter é armazenado em cache com base em suas dependências e só será reavaliado quando algumas de suas dependências forem alteradas.
Os getters receberão o estado como 1º argumento:
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)
}
}
})
Os getters serão expostos no objeto store.getters
e você acessa valores como propriedades:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Os getters também recebem outros getters como o 2º argumento:
getters: {
// ...
doneTodosCount (state, getters) {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
Agora podemos usar facilmente isso dentro de qualquer componente:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
Observe que os getters acessados como propriedades são armazenados em cache como parte do sistema de reatividade do Vue.
Você também pode passar argumentos para os getters retornando uma função. Isso é particularmente útil quando você deseja consultar um Array no store:
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
Observe que os getters acessados via métodos serão executados toda vez que você os chamar, e o resultado não será armazenado em cache.
mapGetters
O auxiliar mapGetters simplesmente mapeia os getters do store para os dados computados locais:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// mistura os getters nos dados computatos com o operador spread
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
Se você deseja mapear um getter com um nome diferente, use um objeto:
...mapGetters({
// mapeia `this.doneCount` para `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})