Vuex conventions
We need to establish some rules for vuex. It’s a proposition, which after some discussion will be added to our docs for possible referencing in future.
Module
Vuex module should be created for specific set of functionalities. Should also have only absolutely necessary dependencies to other modules.
Name of module should be short, quite clear about it’s destination and has words separated by dash.
Good examples:
products
product
user
checkout
compare-products
notifications
order
Bad examples:
next-module
compare (because it’s not saying what its compare)
State
State properties should be simple and their structure should not be nested. Their names are written in camelCase notation and indicates what they are containing.
We should avoid to have more than one instance of object, even between modules. In the vast majority of cases they can be referenced by it’s unique id property. Example:
{
"productsMap": {
"WS08": {
"sku": "WS08",
"name": "Minerva LumaTech™ V-Tee"
// other options
},
"WS12": {
"sku": "WS12",
"name": "Radiant Tee"
// other options
},
"WS08-XS-Black": {
"sku": "WS08-XS-Black",
"name": "Minerva LumaTech™ V-Tee"
// other options
}
// maaaaaaaany more products
},
"currentProductId": "WS08-XS-Black",
"wishlist": ["MP01-32-Black", "MSH05-32-Black"],
"cartItems": [
{
"sku": "WH09-XS-Green",
"qty": 3
},
{
"sku": "WH09-S-Red",
"qty": 1
}
]
}
Good examples:
categoriesMap
currentCategoryId
order
productParentId
Bad examples
list
elements
filters: {
available: {},
chosen: {}
},
Getters
Vuex state, except of mutations, should always be accessed by getters. Including actions.
Getter should:
start from is when returns Boolean, or get otherwise
answer to question what am I returning?
contain module name to ensure that getter is unique through whole vuex. But I doesn’t have to start with that name - first of all it should have natural name.
So for example we have module category and in state availableFilters. So what am I returning? -> available Filters. And this filters are category filters . Its not a Boolean, it’s array or map so we’re starting with get -> getAvailableCategoryFilters
Good examples:
for state user -> isUserLoggedIn, getUser
for state availableFilters -> getAvailableCategoryFilters
for state currentProductId -> getCurrentProduct (because it gets product object from map), getCurrentProductId
Bad examples:
totals
product
current
list
Actions
It’s a heart of logic for module. Every state change from outside of module should be invoked as an action. Actions are meant to:
fetch something from server(or cache) - in this case they have to be asynchronous (return promise)
mutate state of current module
dispatch actions from same module (to avoid repeating logic)
dispatch actions from another modules (only if it’s absolutely required)
Their names should most possibly be unique and in simple way says what specific action is doing. Almost every action should return promise
Good examples:
fetchProduct - gets product by id from server or cache, sets it in products map and returns it by getter
findProducts - fetches products by specific query, sets them in products map and returns them as array
setCurrentProduct - param could be id, it could dispatch fetchProduct, mutate it to productsMap and mutate its id to currentProductId. Also if productId is null then it removes currentProduct.
addCartItem
toggleMicrocart
Bad examples:
list
products
reset
Mutations
Finally we have mutations. Only mutations can change state of module. They should be synchronous (never returns promise), not contain any logic (be extremely fast) except one needed to keep state as it should be (for example sets default value for state). Mutations should be invoked only by actions from the same module. In most cases it should be only a single action which invokes specific mutation.
Types of mutation:
SET_ - it’s the most common type of mutation. It can set an object (or whole array), set default value of object (or maybe clean array),
ADD_ - it can add new element to state property which is an array or add new element to Map
REMOVE_ - an opposite to ADD. It can remove map element or array element by index (or by finding object which is not recommended way on big arrays, then mutation could be slow)
Good examples:
ADD_PRODUCT
SET_CURRENT_PRODUCT_ID
ADD_CATEGORY_FILTER
REMOVE_WISHLIST_PRODUCT_ID
Bad examples:
CATEGORY_UPD_CURRENT_CATEGORY
TAX_UPDATE_RULES
Thats it ;)
It’s a first draft proposition. It’ll be updated after discussions and at the end we will add it to our docs.
Please share your thoughts, every input is welcome and needed. We need to establish this ground rules to get clear and common vision for where are we're going with Vuex.