最近接觸的項目比較經常使用vuex,由於以前基本不涉及vuex的使用,這裏作一下記錄。
首先表達一下見解:vuex是主要是用到存放一些全局的變量,能夠當作是全局式的響應變量,便於統一管理,因此比較適合存取數據字典。vue
包含了store
中存儲的各個狀態
Vuex 使用state
來存儲應用中須要共享的狀態。爲了能讓 Vue 組件在state
更改後也隨着更改,須要基於state
建立計算屬性。vuex
相似於 Vue 中的計算屬性,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。
Getter 方法接受state
做爲其第一個參數:數組
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, getters: { // 默認前兩個參數 doneTodos: (state, getters) => { return state.todos.filter(todo => todo.done) } } })
Getter 會暴露爲store.getters
對象,能夠以屬性的形式訪問這些值緩存
store.getters.doneTodos
注意:getter 在經過屬性訪問時是做爲 Vue 的響應式系統的一部分緩存其中的。異步
一組方法,是改變store
中狀態的執行者,只能是同步操做函數
更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。也就是說,前面兩個都是狀態值自己,mutations
纔是改變狀態的執行者。
Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的事件類型 (type)和 一個回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數:this
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state, n) { // 變動狀態 state.count += n } } })
this.$store.commit('increment', 10)
規範的發起mutation
的方式以下:spa
// 以載荷形式 store.commit('increment',{ amount: 10 //這是額外的參數 }) // 或者使用對象風格的提交方式 store.commit({ type: 'increment', amount: 10 //這是額外的參數 })
額外的參數會封裝進一個對象,做爲第二個參數傳入mutation
定義的方法中。code
mutations: { increment (state, payload) { state.count += payload.amount } }
注意:mutations
只能是同步地更改狀態。對象
一組方法,含有異步操做的時候調用
想要異步地更改狀態,就須要使用action
。action
並不直接改變state
,而是發起mutation
。
Action 函數接受一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用context.commit
提交一個 mutation,或者經過context.state
和context.getters
來獲取 state 和 getters。
actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }
Action 相似於 mutation,不一樣在於:
因爲使用單一狀態樹,應用的全部狀態會集中到一個比較大的對象。當應用變得很是複雜時,store 對象就有可能變得至關臃腫。
這時咱們能夠將 store 分割爲模塊(module),每一個模塊擁有本身的state
、getters
、mutations
、actions
、甚至是嵌套子模塊——從上至下進行一樣方式的分割。
代碼示例:
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 的狀態 store.state.b // -> moduleB 的狀態
將state
和getter
結合進組件須要使用計算屬性:
computed: { count () { return this.$store.state.count // 或者 return this.$store.getter.count } }
將mutation
和action
結合進組件須要在methods
中調用this.$store.commit()
或者this.$store.commit()
:
methods: { changeDate () { this.$store.commit('change'); }, changeDateAsync () { this.$store.commit('changeAsync'); } }
爲了簡便起見,Vuex 提供了四個輔助函數方法用來方便的將這些功能結合進組件。
mapState
mapGetters
mapMutations
mapActions
示例代碼:
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex' export default { // ... computed: { localComputed () { /* ... */ }, // 使用對象展開運算符將此對象混入外部對象中 ...mapState({ // 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數 count(state) { return state.count + this.localCount } }), ...mapGetters({ getterCount(state, getters) { return state.count + this.localCount } }) } methods: { ...mapMutations({ // 若是想將一個屬性另取一個名字,使用如下形式。注意這是寫在對象中 add: 'increment' // 將 `this.add()` 映射爲`this.$store.commit('increment')` }), ...mapActions({ add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')` }) } }
若是結合進組件以後不想改變名字,能夠直接使用數組的方式。
methods: { ...mapActions([ 'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')` // `mapActions` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)` ]), }