
本文基本上是官方教程的盜版,用通俗易懂的文字講解Vuex,也對原文內(nèi)容有刪減。
如果你對以上聲明不介意,那么就可以繼續(xù)看本文,希望對你有所幫助。
學(xué)習(xí)一個新技術(shù),必須要清楚兩個W,"What && Why"。
"XX 是什么?","為什么要使用 XX ,或者說 XX 有什么好處",最后才是"XX 怎么使用"。
Vuex是什么?
Vuex 類似 Redux 的狀態(tài)管理器,用來管理Vue的所有組件狀態(tài)。
為什么使用Vuex?
當(dāng)你打算開發(fā)大型單頁應(yīng)用(SPA),會出現(xiàn)多個視圖組件依賴同一個狀態(tài),來自不同視圖的行為需要變更同一個狀態(tài)。
遇到以上情況時候,你就應(yīng)該考慮使用Vuex了,它能把組件的共享狀態(tài)抽取出來,當(dāng)做一個全局單例模式進(jìn)行管理。這樣不管你在何處改變狀態(tài),都會通知使用該狀態(tài)的組件做出相應(yīng)修改。
下面講解如何使用Vuex。
最簡單的Vuex示例
本文就不涉及如何安裝Vuex,直接通過代碼講解。
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
以上就是一個最簡單的Vuex,每一個Vuex應(yīng)用就是一個store,在store中包含組件中的共享狀態(tài)state和改變狀態(tài)的方法(暫且稱作方法)mutations。
需要注意的是只能通過mutations改變store的state的狀態(tài),不能通過store.state.count = 5;直接更改(其實(shí)可以更改,不建議這么做,不通過mutations改變state,狀態(tài)不會被同步)。
使用store.commit方法觸發(fā)mutations改變state:
store.commit('increment');
console.log(store.state.count) // 1
一個簡簡單單的Vuex應(yīng)用就實(shí)現(xiàn)了。
在Vue組件使用Vuex
如果希望Vuex狀態(tài)更新,相應(yīng)的Vue組件也得到更新,最簡單的方法就是在Vue的computed(計(jì)算屬性)獲取state
// Counter 組件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count;
}
}
}
上面的例子是直接操作全局狀態(tài)store.state.count,那么每個使用該Vuex的組件都要引入。為了解決這個,Vuex通過store選項(xiàng),提供了一種機(jī)制將狀態(tài)從根組件注入到每一個子組件中。
// 根組件
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const app = new Vue({
el: '#app',
store,
components: {
Counter
},
template: `
<div class="app">
<counter></counter>
</div>
`
})
通過這種注入機(jī)制,就能在子組件Counter通過this.$store訪問:
// Counter 組件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
mapState函數(shù)
computed: {
count () {
return this.$store.state.count
}
}
這樣通過count計(jì)算屬性獲取同名state.count屬性,是不是顯得太重復(fù)了,我們可以使用mapState函數(shù)簡化這個過程。
import { mapState } from 'vuex';
export default {
computed: mapState ({
count: state => state.count,
countAlias: 'count', // 別名 `count` 等價于 state => state.count
})
}
還有更簡單的使用方法:
computed: mapState([
// 映射 this.count 為 store.state.count
'count'
])
Getters對象
如果我們需要對state對象進(jìn)行做處理計(jì)算,如下:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
如果多個組件都要進(jìn)行這樣的處理,那么就要在多個組件中復(fù)制該函數(shù)。這樣是很沒有效率的事情,當(dāng)這個處理過程更改了,還有在多個組件中進(jìn)行同樣的更改,這就更加不易于維護(hù)。
Vuex中getters對象,可以方便我們在store中做集中的處理。Getters接受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)
}
}
})
在Vue中通過store.getters對象調(diào)用。
computed: {
doneTodos () {
return this.$store.getters.doneTodos
}
}
Getter也可以接受其他getters作為第二個參數(shù):
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
mapGetters輔助函數(shù)
與mapState類似,都能達(dá)到簡化代碼的效果。mapGetters輔助函數(shù)僅僅是將store中的getters映射到局部計(jì)算屬性:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用對象展開運(yùn)算符將 getters 混入 computed 對象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
上面也可以寫作:
computed: mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
所以在Vue的computed計(jì)算屬性中會存在兩種輔助函數(shù):
import { mapState, mapGetters } from 'vuex';
export default {
// ...
computed: {
mapState({ ... }),
mapGetter({ ... })
}
}
Mutations
之前也說過了,更改Vuex的store中的狀態(tài)的唯一方法就是mutations。
每一個mutation都有一個事件類型type和一個回調(diào)函數(shù)handler。
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 變更狀態(tài)
state.count++
}
}
})
調(diào)用mutation,需要通過store.commit方法調(diào)用mutation type:
store.commit('increment')
Payload 提交載荷
也可以向store.commit傳入第二參數(shù),也就是mutation的payload:
mutaion: {
increment (state, n) {
state.count += n;
}
}
store.commit('increment', 10);
單單傳入一個n,可能并不能滿足我們的業(yè)務(wù)需要,這時候我們可以選擇傳入一個payload對象:
mutation: {
increment (state, payload) {
state.totalPrice += payload.price + payload.count;
}
}
store.commit({
type: 'increment',
price: 10,
count: 8
})
mapMutations函數(shù)
不例外,mutations也有映射函數(shù)mapMutations,幫助我們簡化代碼,使用mapMutations輔助函數(shù)將組件中的methods映射為store.commit調(diào)用。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment' // 映射 this.increment() 為 this.$store.commit('increment')
]),
...mapMutations({
add: 'increment' // 映射 this.add() 為 this.$store.commit('increment')
})
}
}
注 Mutations必須是同步函數(shù)。
如果我們需要異步操作,Mutations就不能滿足我們需求了,這時候我們就需要Actions了。
Aciton
相信看完之前的Vuex的內(nèi)容,你就已經(jīng)入門了。那么Action就自己進(jìn)行學(xué)習(xí)吧(Action有點(diǎn)復(fù)雜,我還需要時間消化)。
結(jié)語
上個月看Vuex還是一頭霧水,現(xiàn)在看來Vuex也是很容易理解的。
學(xué)習(xí)一門新技術(shù)最重要的就是實(shí)踐,單單看教程和demo是遠(yuǎn)遠(yuǎn)不夠的。
前端路途漫漫,共勉。