Sometimes we may need to compute derived state based on store state, for example filtering through a list of items and counting them:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
If more than one component needs to make use of this, we have to either duplicate the function, or extract it into a shared helper and import it in multiple places - both are less than ideal.
Vuex allows us to define "getters" in the store (think of them as computed properties for stores). Getters will receive the state as their 1st argument:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
The getters will be exposed on the store.getters
object:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Getters will also receive other getters as the 2nd argument:
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
We can now easily make use of it inside any component:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
You can also pass arguments to getters by returning a function. This is particularly useful when you want to query an array in the store:
getters: {
// ...
getTodoById: (state, getters) => (id) => {
return getters.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
mapGetters
HelperThe mapGetters
helper simply maps store getters to local computed properties:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// mix the getters into computed with object spread operator
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
If you want to map a getter to a different name, use an object:
...mapGetters({
// map this.doneCount to store.getters.doneTodosCount
doneCount: 'doneTodosCount'
})