What is Vuex?
Bài đăng này đã không được cập nhật trong 6 năm
Vuex là thư viện giúp quản lý trạng thái các component trong Vue.js, nó là nơi lưu trữ tập trung cho tất cả các component trong một ứng dụng.
Các thành phần trong Vuex
I. State – trạng thái
Vuex sử dụng một cây trạng thái duy nhất, đối tượng này sẽ chứa tất các trạng thái của ứng dụng. Để sử dụng các trạng thái trong Vue component, chúng ta sẽ lấy các trạng thái và trả về trong thuộc tính computed của component:
// let's create a Counter component
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
Vuex cung cấp cơ chế giúp sử dụng store ở tất cả các component con từ component cha với tùy chọn store:
const app = new Vue({
el: '#app',
// provide the store using the "store" option.
// this will inject the store instance to all child components.
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
Các component con có thể truy xuất store thông qua this.$store
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
The mapState Helper
Khi 1 component cần sử dụng nhiều thuộc tính state, getter. Việc khai báo tất cả các thuộc tính có thể lặp đi lặp lại k cần thiết. Để giải quyết vấn đề này, chúng ta có thể sử dụng helper mapState
để tạo ra các hàm getter được tính toán cho chúng ta
// in full builds helpers are exposed as Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// arrow functions can make the code very succinct!
count: state => state.count,
// passing the string value 'count' is same as `state => state.count`
countAlias: 'count',
// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
Ta cũng có thể truyền một mảng chuỗi cho mapState
computed: mapState([
// map this.count to store.state.count
'count'
])
II. Getter – bộ lọc trạng thái
Đôi khi chúng ta cần lấy các trạng thái dựa vào việc tính toán, filter các trạng thái được cung cấp bởi kho lưu trữ.
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
Nếu có nhiều component, có thể định nghĩa getter trong store để thực hiện.
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)
}
}
})
Property-Style Access
Bạn có thể truy xuất các trạng thái đã được filter bằng cách sử dụng cú pháp
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Getters cũng sẽ nhận các getters khác làm đối số thứ 2:
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
Bây giờ ta có thể dễ dàng sử dụng nó bên trong bất kỳ component nào:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
Method-Style Access
Bạn cũng có thể truyền đối số tới getters bằng cách trả về một hàm. Điều này đặc biệt hữu ích khi bạn muốn truy vấn một mảng trong store.
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
The mapGetters Helper
mapGetters
Hiểu đơn giản là ánh xạ các thuộc tính store getters:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// mix the getters into computed with object spread operator
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
Nếu bạn muốn ánh xạ một getter đến một tên khác, có thể sử dụng như sau,
...mapGetters({
// map `this.doneCount` to `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
###III. Mutations – thay đổi trạng thái Trạng thái không thể thay đổi trực tiếp mà chỉ được thay đổi thông qua commit, Vuex mutation tương tự như các events, mỗi mutation có kiểu chuỗi và một handler. Handler function là nơi chúng ta thực hiện các thay đổi trạng thái và nó cần được truyền vào tham số đầu tiên là state.
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// mutate state
state.count++
}
}
})
Bạn không thể gọi trực tiếp một handler của mutation, mà cần phải được thực hiện bằng cách sử dụng store.commit
store.commit('increment')
Có thể truyền thêm tham số cho các handler trong mutation:
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
IV. Action – hành động
Action cũng gầm giống mutation, có một vài điểm khác biệt
- Thay vì thay đổi trạng thái, action commit các thay đổi.
- Action có thể chứa các hoạt động không đồng bộ.
VD:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Ta có thể gọi context.commit
để commit một thay đổi hoặc truy xuất trạng thái và getter thông qua context.state
và context.getter
Các action sẽ được trigger khi sử dụng phương thức store.dispatch
store.dispatch('increment')
Nếu chúng ta muốn tăng trạng thái count , tại sao không gọi store.commit(‘increment’)
trực tiếp? Lưu ý rằng, mutation
cần phải đồng bộ, nhưng với action
thì không, chúng ta thực hiện các hoạt động không đồng bộ trong một action
.
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
Link docs: https://vuex.vuejs.org/en/intro.html
All rights reserved