yarn add vuexhtml
一、vuex流程圖vue
vuex能夠幫助咱們管理組件間公共的數據git
建立一個 store github
// 若是在模塊化構建系統中,請確保在開頭調用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } })
如今,你能夠經過 store.state
來獲取狀態對象,以及經過 store.commit
方法觸發狀態變動:vuex
store.commit('increment') console.log(store.state.count) // -> 1
二、詳解(state)數組
因爲 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態:緩存
// 建立一個 Counter 組件 const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { return store.state.count } } }
每當 store.state.count
變化的時候, 都會從新求取計算屬性,而且觸發更新相關聯的 DOM。app
這種模式致使組件依賴全局狀態單例ecmascript
因此,異步
Vuex 經過 store
選項,提供了一種機制將狀態從根組件「注入」到每個子組件中(需調用 Vue.use(Vuex)
):
const app = new Vue({ el: '#app', // 把 store 對象提供給 「store」 選項,這能夠把 store 的實例注入全部的子組件 store, components: { Counter }, template: ` <div class="app"> <counter></counter> </div> ` })
經過在根實例中註冊 store
選項,該 store 實例會注入到根組件下的全部子組件中,且子組件能經過 this.$store
訪問到。讓咱們更新下 Counter
的實現:
const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { return this.$store.state.count } } }
mapState輔助函數
當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。
爲了解決這個問題,咱們可使用 mapState
輔助函數幫助咱們生成計算屬性,讓你少按幾回鍵:
// 在單獨構建的版本中輔助函數爲 Vuex.mapState import { mapState } from 'vuex' export default { // ... computed: mapState({ // 箭頭函數可以使代碼更簡練 count: state => state.count, // 傳字符串參數 'count' 等同於 `state => state.count` countAlias: 'count', // 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數 countPlusLocalState (state) { return state.count + this.localCount } }) }
三、詳解(Getter)
我的理解:至關於獲取計算後的state,將state中某個狀態進行過濾,而後獲取新的狀態
Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。
就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,
且只有當它的依賴值發生了改變纔會被從新計算。
Getter 接受 state 做爲其第一個參數:
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 會暴露爲 store.getters
對象,你能夠以屬性的形式訪問這些值:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Getter 也能夠接受其餘 getter 做爲第二個參數:
getters: { // ... doneTodosCount: (state, getters) => { return getters.doneTodos.length } }
能夠經過讓 getter 返回一個函數,來實現給 getter 傳參。在你對 store 裏的數組進行查詢時很是有用。
getters: { // ... getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
getter 在經過方法訪問時,每次都會去進行調用,而不會緩存結果
mapGetters輔助函數
僅僅是將 store 中的 getter 映射到局部計算屬性:
import { mapGetters } from 'vuex' export default { // ... computed: { // 使用對象展開運算符將 getter 混入 computed 對象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ]) } }
四、詳解(Mutation)
更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation
Vuex 中的 mutation 很是相似於事件:
每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。
這個回調函數就是咱們實際進行狀態更改的地方,
而且它會接受 state 做爲第一個參數:
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 變動狀態 state.count++ } } })
store.commit('increment')
能夠向 store.commit
傳入額外的參數,即 mutation 的 載荷(payload):
// ... mutations: { increment (state, n) { state.count += n } } store.commit('increment', 10)
mutation 必須是同步函數
你能夠在組件中使用 this.$store.commit('xxx')
提交 mutation,
或者使用 mapMutations
輔助函數將組件中的 methods 映射爲
store.commit
調用(須要在根節點注入 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 內部執行異步操做:
actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }
Actions 支持一樣的載荷方式和對象方式進行分發:
// 以載荷形式分發 store.dispatch('incrementAsync', { amount: 10 }) // 以對象形式分發 store.dispatch({ type: 'incrementAsync', amount: 10 })
在組件中使用 this.$store.dispatch('xxx')
分發 action,
或者使用 mapActions
輔助函數將組件的 methods 映射爲
store.dispatch
調用(須要先在根節點注入 store
):
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')` // `mapActions` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')` }) } }
store.dispatch
能夠處理被觸發的 action 的處理函數返回的 Promise,
而且 store.dispatch
仍舊返回 Promise:
actions: { actionA ({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) } }
一個action中
store.dispatch('actionA').then(() => { // ... })
另外一個action中
actions: { // ... actionB ({ dispatch, commit }) { return dispatch('actionA').then(() => { commit('someOtherMutation') }) } }
咱們利用 async / await
// 假設 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
一個 store.dispatch
在不一樣模塊中能夠觸發多個 action 函數。
在這種狀況下,只有當全部觸發函數完成後,返回的 Promise 纔會執行。
之後再更。