-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Description
Request for enhancing the documentation
This has been discussed in several other Issues (for example #526 and #456), and as someone who is learning Vue + Vuex who just went through the same issue, it would be very helpful to have such common cases in the official docs, instead of in the closed issues
Accessing array data is not an isolated use-case, but instead an absolute necessity for larger applications
Reasoning below (if there is another, better Vuex way, please share it)
vuex is playing the role from one side as a simple abstraction of the application data//the state, similar to the DBContext layer in the ORM world
const state = {
products = [
{ id:1, fullName:'foo', price: 200, color: 'red' },
{ id:2, fullName:'bar', price: 999, color: 'blue' }
]
}
//and the abstraction over direct data access, similar to the DBSets in ORMs
const getters = {
products(state){
return state.products
},
//or simply
products: state=>
}
But also as a repository pattern substitute, where data changes are done through mutations.
const mutations = {
//addProduct(state, payload)
addProduct(state, { fullName, price, color }){
state.products.push({
fullName,
price,
color,
id: generateProductId()
})
}
}
In that sense, I felt that Vuex is in an odd spot (I was comparing Vuex with a standard data repository pattern) where data changes are abstracted within the scope of vuex (mutations), but data getting of array items is supposed to be carried out by a separate application layer, instead of having commonly used getters with arguments:
const dynamicGetters = {
getProductById: (state, getters, payload) => {
return getters.products.find(x=> x.id === payload)
},
getProduct: (state, getters, { name, color }) => {
return getters.products.find(x=> x.fullName === name && x.color === color)
}
}
so that queries used from different parts of the application can be cached in a centralized location (the ORM/DB way of thinking, obviously not valid in the Vue + Vuex world) and only specific, non-standard queries are moved to their own layer
It is fairly obvious that getters can return functions once you see it, but not so much when you have OOP background
Hopefully this helps others - the upper dynamicGetters (these don't exist in vuex) represented as standard getters that return functions, as suggested by @ktsn :
const getters = {
//ES6
getProductById: (state, getters) => (id) =>{
return getters.products.find(x=> x.id === id)
},
//function syntax
getProductById: function(state, getters){
return function(id){
return getters.products.find(x=> x.id === id)
}
},
getProduct: (state, getters) => ( { name, color } ) {
return getters.find(x=> x.fullName === name && x.color === color)
}
}
//and then used in the vue instance (state and getters get automatically injected)
//where preferably the output product should be a computed property instead of direct methods
let product1 = this.$store.getters.getProductById(2)
let query = {
name: 'foo',
color: 'red'
}
let product2 = this.$store.getters.getProduct(query)