Vuex 使用單一狀態(tài)樹——是的,用一個對象就包含了全部的應用層級狀態(tài)艘狭。至此它便作為一個“唯一數(shù)據(jù)源 (SSOT (opens new window))”而存在挎扰。這也意味著,每個應用將僅僅包含一個 store 實例巢音。
State:儲存數(shù)據(jù)遵倦,類似vue中的data。
vue中讀取state中的值官撼,由于 Vuex 的狀態(tài)存儲是響應式的骇吭,從 store 實例中讀取狀態(tài)最簡單的方法就是在計算屬性 (opens new window)中返回某個狀態(tài):
調(diào)用 Vue.use(Vuex)
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}}
}
mapState
輔助函數(shù)
當一個組件需要獲取多個狀態(tài)的時候,將這些狀態(tài)都聲明為計算屬性會有些重復和冗余歧寺。為了解決這個問題燥狰,我們可以使用 mapState
輔助函數(shù)幫助我們生成計算屬性,讓你少按幾次鍵:
// 在單獨構(gòu)建的版本中輔助函數(shù)為 Vuex.mapState
import { mapState } from 'vuex'export default {// ...
computed: mapState({// 箭頭函數(shù)可使代碼更簡練count: state => state.count,// 傳字符串參數(shù) 'count' 等同于 `state => state.count`
countAlias: 'count',// 為了能夠使用 `this` 獲取局部狀態(tài)斜筐,必須使用常規(guī)函數(shù)countPlusLocalState (state) {return state.count + this.localCount
}})
}
當映射的計算屬性的名稱與 state 的子節(jié)點名稱相同時龙致,我們也可以給 mapState
傳一個字符串數(shù)組。
computed: mapState([// 映射 this.count 為 store.state.count
'count'
])
mapState
函數(shù)返回的是一個對象顷链。與局部計算屬性混合使用
computed: {
localComputed () {
/* ... */
},// 使用對象展開運算符將此對象混入到外部對象中
...mapState({
// ...
})
}
Getter:(可以認為是 store 的計算屬性)目代。就像計算屬性一樣,getter 的返回值會根據(jù)它的依賴被緩存起來嗤练,且只有當它的依賴值發(fā)生了改變才會被重新計算榛了。
Getter 接受 state 作為其第一個參數(shù):
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)
}
}
})
Getter 也可以接受其他 getter 作為第二個參數(shù):
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
我們可以很容易地在任何組件中使用它:
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
注意,getter 在通過屬性訪問時是作為 Vue 的響應式系統(tǒng)的一部分緩存其中的煞抬。
也可以通過讓 getter 返回一個函數(shù)霜大,來實現(xiàn)給 getter 傳參。在對 store 里的數(shù)組進行查詢時非常有用革答。
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
注意战坤,getter 在通過方法訪問時,每次都會去進行調(diào)用残拐,而不會緩存結(jié)果途茫。
mapGetters
輔助函數(shù)
mapGetters
輔助函數(shù)僅僅是將 store 中的 getter 映射到局部計算屬性:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用對象展開運算符將 getter 混入 computed 對象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
如果你想將一個 getter 屬性另取一個名字遗遵,使用對象形式:
...mapGetters({
// 把 `this.doneCount` 映射為 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
Mutation
更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation披摄。
Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調(diào)函數(shù) (handler)戴差。這個回調(diào)函數(shù)就是我們實際進行狀態(tài)更改的地方昔字,并且它會接受 state 作為第一個參數(shù):
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {// 變更狀態(tài)
state.count++
}
}
})
不能直接調(diào)用一個 mutation handler悉患。這個選項更像是事件注冊:“當觸發(fā)一個類型為 increment
的 mutation 時搬卒,調(diào)用此函數(shù)业扒《3疲”要喚醒一個 mutation handler,你需要以相應的 type 調(diào)用 store.commit 方法:
store.commit('increment')
你可以向 store.commit
傳入額外的參數(shù)笑窜,即 mutation 的 載荷(payload):
// ...
mutations: {increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
在大多數(shù)情況下致燥,載荷應該是一個對象,這樣可以包含多個字段并且記錄的 mutation 會更易讀:
// ...
mutations: {increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
提交 mutation 的另一種方式是直接使用包含 type
屬性的對象:
store.commit({
type: 'increment',
amount: 10
})
當使用對象風格的提交方式排截,整個對象都作為載荷傳給 mutation 函數(shù)嫌蚤,因此 handler 保持不變:
mutations: {increment (state, payload) {
state.count += payload.amount
}
}
Mutation 必須是同步函數(shù)
在組件中使用 this.$store.commit('xxx')
提交 mutation,或者使用 mapMutations
輔助函數(shù)將組件中的 methods 映射為 store.commit
調(diào)用(需要在根節(jié)點注入 store
)断傲。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment',
// 將 `this.increment()` 映射為 `this.$store.commit('increment')`
// `mapMutations` 也支持載荷:
'incrementBy'
// 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 將 `this.add()` 映射為 `this.$store.commit('increment')`
})
}
}
Action:
Action 類似于 mutation脱吱,不同在于:
Action 提交的是 mutation,而不是直接變更狀態(tài)认罩。
Action 可以包含任意異步操作箱蝠。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {increment (state) {
state.count++
}
},
actions: {increment (context) {
context.commit('increment')
}
}
})
Module:
將 store 分割成模塊(module)。每個模塊擁有自己的 state垦垂、mutation宦搬、action、getter劫拗、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)
Vuex官網(wǎng):https://v3.vuex.vuejs.org/zh/