在進行復雜一點的項目開發時,咱們會發現只是普通的組件間的數據傳遞已經不足以知足咱們的需求,因此咱們須要引入Vue中管理狀態工具--Vuex
// 若是在模塊化構建系統中,請確保在開頭調用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }) store.commit('increment')// 經過commit去觸發mutations中的increment方法 console.log(store.state.count) // -> 1
在Vuex中使用state保存了所有的應用層級的狀態,咱們能夠經過store.state.[變量名]去獲取狀態值,在一般的狀況下,咱們能夠直接在每一個須要使用state的組件中引入store,可是這種方式會頻繁地在各個組件中導入,會影響性能;因此通常的解決方法是先在根實例中註冊store,該實例會註冊到子組件中,這樣的話,在子組件中咱們就能夠經過this.$store.state.[變量名]去獲取到想要的狀態。vue
// 第一種方式:在使用到state的組件中引入store const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { // 經過計算屬性去返回狀態 return store.state.count } } } // 第二種方式:在根組件的實例中,把 store 對象提供給 「store」 選項 const app = new Vue({ el: '#app', store, components: { Counter }, template: ` <div class="app"> <counter></counter> </div> ` }) const Counter = { template: `<div>{{ count }}</div>`, computed: { count () { return this.$store.state.count // 在子組件中只須要使用this.$store就可使用 } } }
前面說state的使用方法時,咱們說到能夠經過計算屬性的去拿到想要獲取的狀態,可是若是咱們要在同一個組件中獲取多個狀態時,咱們就能夠利用mapState了,下面是它的用法:vuex
// 在store實例的state中存放值 state: { name: '', age: '', sex: '' } // 在子組件的計算屬性中去獲取store中存放的值 compute: { ...mapState(['name']) }
getter主要是用來存放由state派生出的一些狀態,若是不少組件都須要使用到這個狀態,就須要在每一個組件中根據state計算再計算一遍,這樣就容易形成代碼的冗餘。store中提供了一個getter屬性,能夠專門用來存放store中的state衍生出來的狀態,以下面的用法:數組
// state中存放的是todos屬性 const store = new Vuex.Store({ state: { todos: [ { id: 1, done: true }, { id: 2, done: false } ] }, getters: {// getters中存放的是由state派生出來,會屢次用到的值 doneTodos: state => {// 第一個參數是state return state.todos.filter(todo => todo.done) } } })
能夠經過store.getters去獲取Getter對象,而後經過訪問屬性的方式去獲取getters中的內容,好比下例:promise
store.getters.doneTodos // -> [{ id: 1, done: true }]
getters也能夠將本身做爲參數使用,在方法中直接獲取getters中的內容:緩存
getters: { // 獲取doneTodos的長度 doneTodosCount: (state, getters) => { return getters.doneTodos.length } }
能夠經過在getter中返回一個函數來給getter傳參,這個比較適用於查找store中的數組,好比下面的用法:app
getters: { // 經過給getTodoById傳入id來獲取對應的項 getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } store.getters.getTodoById(2) // -> { id: 2, done: false }
使用屬性的方式去訪問有緩存,經過方法去訪問的話,每次都會被調用一次,不會有緩存。異步
mapGetters和mapStates是同樣的做用,都是爲了便於在子組件中獲取多個狀態,用法也相似,這裏就很少說明了。async
在Vuex中,mutations的角色就至關因而vue中的methods,它能夠用來存放方法,mutations中的類型名就至關因而methods中的方法名,每一個mutation中的會有一個回調函數,可是在methods中能夠沒有返回值。模塊化
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 變動狀態 state.count++ } } }) // 經過commit去使用mutations中的方法,這也是改變state中的狀態的惟一方法 store.commit('increment')
在commit的時候也能夠傳入額外的參數,即mutation的載荷(payload),一般這個參數會傳入一個對象,以下面的用法:函數
mutations: { increment (state, payload) { state.count += payload.amount } } // 在commit的時候給他傳遞一個對象,這樣的好處是更加易懂明瞭 store.commit('increment', { amount: 10 }) // 還可使用對象的方式去提交 store.commit({ type: 'increment', amount: 10 })
在一個大型項目中,Mutations中的事件可能會比較多,這時將每種類型都用一個常量去表示,而後將這些常量放在一個靜態文件中,打開靜態文件,就能夠一目瞭然地看到Mutations中有哪些事件,好比下面的用法:
// mutation-types.js // 在存放類型名的文件中將該類型常量拋出來 export const SOME_MUTATION = 'SOME_MUTATION' // store.js // 在store中引入該常量 import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({ state: { ... }, mutations: { [SOME_MUTATION] (state) { // ... } } })
以前咱們說到過若是想要改變state,惟一的方法就是使用commit去改變,這樣作是由於咱們想要更明確地跟蹤state狀態的變化。若是mutation是異步函數的話,就不知道state具體是什麼時間發送變化的,這就和以前設計的初衷相悖了。還有可能有多個異步mutation時,使用commit去改變的話就分辨不出來是哪一個先進行回調,因此這也是比較麻煩的事。
爲了解決異步回調的問題,Vuex中定義了一個相似於mutation的action,action是專門處理異步問題的,它接受一個和store變量具備相同屬性和方法的對象--context,因此能夠用該對象去調用commit進行提交。
action和mutation有如下兩點區別:
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, // 在actions中去調用mutations中的方法 actions: { increment (context) { context.commit('increment') } } })
以前說過在action中能夠提交mutations,可是它不只僅是用來提交同步函數的,還能夠在其中執行異步操做,以下用法:
// 在actions中執行異步操做 actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }
// 能夠經過store.dispatch去觸發action store.dispatch('incrementAsync') // 和commit相似,dispatch也可使用對象的方式載荷發佈 store.dispatch('incrementAsync', { amount: 10 }) store.dispatch({ type: 'incrementAsync', amount: 10 })
在組件中分發action的方式有兩種:
// 使用this.$store.dispatch分發 this.$store.dispatch('incrementAsync') // 使用mapActions將組件中的方法映射爲store.dispatch調用 import { mapActions } from 'vuex' export default { methods: { ...mapActions([ // 將this.increment()映射成this.$store.dispatch('increment') 'increment', // 將this.increment(amount)映射成this.$store.dispatch('increment', amount) 'incrementBy' ]), ...mapActions([ // 將this.add()映射成this.$store.dispatch('increment') add: 'increment' ]) } }
使用dispatch返回的是promise對象,而且在dispatch中也能夠處理promise對象,用法以下:
actions: { // actionA返回的是一個promise對象 actionA ({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('someMutation') resolve() }, 1000) }) } }
store.dispatch('actionA')
actions: { actionB ({ commit, dispatch }) { return dispatch('actionA').then(() => { commit('someMutation') }) } }
// 假設 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
基本內容就是這麼多了,項目中目前使用到的就是這些,這篇文章只是對Vuex經常使用內容的一個總結,更多的東西能夠去看Vuex官網,若是有什麼錯誤歡迎指出哦~