(注:本文適用於有一定Vue基礎或開發經驗的讀者,文章就知識點的講解不一定全面,但卻是開發過程中很實用的)
概念:Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
應用場景:Vue多個組件之間需要共享數據或狀態。
Vuex有幾個核心概念:State、Getter、Mutation、Action、Module。
State:存儲狀態數據
Getter:從狀態數據派生數據,相當於State的計算屬性。
Mutation:存儲用於同步更改狀態數據的方法,默認傳入的參數為state。
Action:存儲用於異步更改狀態數據,但不是直接更改,而是通過觸發Mutation方法實現,默認參數為context。
Module:Vuex模塊化。
它們之間的交互關系如下圖(來源於官方文檔)所示:
接下來先看一個Vuex應用的簡單實例,新建store.js文件並添加如下代碼:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { name: '' }, getters: { getName(state) { return 'hello ' + state.name; } }, mutations: { mutationSetName(state, name) { state.name = name; } }, actions: { actionSetName(context, name) { setTimeout(() => { context.commit('mutationSetName', name); }, 1000); } } }); export default store;
然后將該store實例注入到所有子組件,方法如下:
import store from './store.js'; new Vue({ el: '#app', router, // 把 store 對象提供給 “store” 選項,這可以把 store 的實例注入所有的子組件 store, components: { App }, template: '<App/>' });
接下來就可以在vue的各個子組件中通過下面的方式訪問vuex對象實例。
this.$store.state.name; this.$store.getters.getName; this.$store.commit('mutationSetName', 'zhangsan'); this.$store.dispatch('actionSetName', 'lisi');
或者也可以通過輔助函數的方式訪問,
1、需要在應用的子組件中引入輔助函數
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
2、在計算屬性computed中注入state和getters
computed: { ...mapState({ // 把 `this.name` 映射為 `this.$store.state.name` name: state => state.name }), ...mapGetters({ // 把 `this.getName` 映射為 `this.$store.getters.getName` getName: getName }) }
3、在methods中注入mutations和actions
methods: { ...mapMutations([ // 將 `this.mutationSetName()` 映射為 `this.$store.commit('mutationSetName')` 'mutationSetName' ]), ...mapActions([ // 將 `this.actionSetName()` 映射為 `this.$store.dispatch('actionSetName')` 'actionSetName' ]) }
模塊化
由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store對象就有可能變得相當臃腫。
為了解決以上問題,Vuex允許我們將store分割成模塊。每個模塊擁有自己的state、getter、mutation、action、甚至是嵌套子模塊-從上到下進行同樣的分割。
下面新建moduleA和moduleB兩個js文件,分別添加如下代碼:
const moduleA = { namespaced: true, state: { name: '' }, getters: {}, mutations: {}, actions: {} } export default moduleA;
const moduleB = { namespaced: true, state: { name: '' }, getters: {}, mutations: {}, actions: {} } export default moduleB;
然后新建store.js文件並引入上述兩個模塊文件,代碼如下:
import moduleA from './moduleA.js'; import moduleB from './moduleB.js'; const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) export default store;
其中a、b為自定義的模塊別名,接下來按前文同樣的方式將store對象注入vue。
訪問方式如下:
this.$store.state.a.name // -> moduleA 的狀態name this.$store.state.b.name // -> moduleB 的狀態name
輔助函數訪問方式和前文所講區別不大,只是多了模塊名稱字段:
computed: { ...mapState('a', { name: state => state.name }), ...mapState('b', { name: state => state.name }) }
其他幾個對象getter、mutation、action的訪問方式類似,都要加上模塊名稱字段。
注意:
1、是否使用Vuex要根據項目的實際規模,在簡單的應用中使用 Vuex 可能會顯得繁瑣冗余;對於中大型的單頁應用,Vuex在狀態管理方面才是最好的選擇。
2、Vuex和單純的全局對象不同。Vuex 的狀態存儲是響應式的,當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
3、不能直接改變 store 中的狀態,改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation,這樣有利於跟蹤每一個狀態的變化。
以上就是vuex的基礎用法,更多詳細的說明請查閱官方文檔:https://vuex.vuejs.org/zh/。