Modules
Store lớn dồn vào một file sẽ khó quản lý. Modules chia store thành các phần độc lập, mỗi module có state, getters, mutations, actions riêng.
Khai báo module
const cart = {
state: () => ({ items: [] }),
getters: {
itemCount(state) {
return state.items.length
}
},
mutations: {
addItem(state, item) {
state.items.push(item)
}
},
actions: {
async checkout({ state, commit }) {
// ...
}
}
}
const user = {
state: () => ({ profile: null })
}
export default new Vuex.Store({
modules: { cart, user }
})
State của module nên là function (giống data của component) để tránh share khi tái sử dụng module.
Truy cập state module
State module nằm lồng dưới tên module trong store state.
this.$store.state.cart.items
this.$store.state.user.profile
Getters, mutations, actions mặc định đăng ký ở namespace toàn cục (gọi không cần tên module). Dễ trùng tên giữa các module.
Namespaced modules
Đặt namespaced: true để getters/mutations/actions của module có tiền tố riêng. Đây là cách nên dùng cho module nghiệp vụ.
const cart = {
namespaced: true,
state: () => ({ items: [] }),
getters: {
itemCount: state => state.items.length
},
mutations: {
addItem(state, item) {
state.items.push(item)
}
},
actions: {
checkout({ commit }) { /* ... */ }
}
}
Gọi với tiền tố cart/:
this.$store.getters['cart/itemCount']
this.$store.commit('cart/addItem', item)
this.$store.dispatch('cart/checkout')
map helpers với namespace
Truyền namespace làm tham số đầu cho gọn.
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
computed: {
...mapState('cart', ['items']),
...mapGetters('cart', ['itemCount'])
},
methods: {
...mapActions('cart', ['checkout'])
}
}
Hoặc dùng createNamespacedHelpers:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('cart')
export default {
computed: { ...mapState(['items']) },
methods: { ...mapActions(['checkout']) }
}
Truy cập gốc từ trong module
Trong action/getter của module namespaced, truy cập state và getter gốc qua tham số bổ sung.
actions: {
someAction({ commit, dispatch, rootState, rootGetters }) {
// commit mutation toàn cục
commit('someGlobalMutation', null, { root: true })
// dispatch action toàn cục
dispatch('someGlobalAction', null, { root: true })
}
}
getters: {
// getter nhận thêm rootState, rootGetters
example(state, getters, rootState, rootGetters) {
return state.items.length + rootState.user.bonus
}
}
Cấu trúc thư mục gợi ý
Project lớn tách mỗi module ra file riêng.
store/
├── index.js # tạo store, gom modules
├── modules/
│ ├── cart.js
│ ├── user.js
│ └── products.js
└── mutation-types.js
Tips cho AEM
Mỗi nhóm chức năng (cart, user, search) làm một namespaced module. Khi nhiều AEM component dùng chung store, mỗi component chỉ map đúng module nó cần, tránh trùng tên và giảm coupling. Module user có thể nhận dữ liệu khởi tạo từ Sling Model server-side, các module khác gọi API qua action.