Vuex狀態管理(下)
文章目錄
一.引言
前面我們Vuex狀態管理(上)我們瞭解了Vuex的五大核心概念的四個概念,State,Getters,Mutations,Actions,接下來我們講講最後一個與項目架構相關的一個核心概念:Module
二.背景
由於使用單一狀態樹,應有的所有的狀態會集中到一個比較大的對象,當應用變得非常複雜時,store對象就有可能變得非常臃腫.
當我們的項目慢慢變得龐大時,數據關聯的複雜性就更加大了,而Vue本就是數據驅動,vuex更是專門的數據狀態倉庫,更容易發生不可預知的關聯性數據錯誤.
爲了解決以上的問題,官方vuex允許我們將store分割成模塊(module) .每個模塊擁有自己的state.getter.mutation,action.甚至是嵌套子模塊一一從上至下進行同樣方式的分割.
項目越做越大,功能點越寫越多,需要使用vuex共享的數據越來越龐大時,就需要使用module來進行倉庫模塊的分割了.
三.在Vuex中使用module
//拆分的倉庫子模塊A
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... },
//倉庫子模塊也可以繼續做拆分,但是無必須要,反而更復雜
modules:{
aaaa,
bbbb,
}
}
//拆分的倉庫子模塊B
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
//倉庫根模塊
const store = new Vuex.Store({
//通過modules選項配置子模塊
modules: {
//key:value形式
//key: a 倉庫模塊的名字
//value :moduleA 對應倉庫子模塊的對象
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態
上面是官網中的示例代碼,我做了點註解.助大家更容易理解模塊的拆分
1.使用步驟
- 在src目錄下新建store目錄
- 在stroe目錄下新建index.js和modules文件夾
- index.js是在Vuex實例中使用modules選項將合併module文件夾下的子模塊合併
- modules文件夾下包含着各個拆分的功能模塊的js文件,同樣裏面包含state,和getters,mutations,actions
index.js
//引入vue
import Vue from 'vue';
//引入vuex
import Vuex from 'vuex';
//註冊
Vue.use(Vuex);
// 這就是一個store子模塊
import A from './modules/a'
import B from './modules/b'
const store = new Vuex.Store({
// modules這個選項用於把子module進行合併
modules: {
A,
B
}
})
export default store
拆分後子模快.js
// 每一個子module實際上就是一個普通json對象,可以包括state、getters、mutations、actions這些選項
const studyModule = {
state: {
},
getters: {
},
mutations: {
},
actions: {
}
}
export default studyModule
後續無論你的功能有多大,只需要添加相應的js文件即可
2.拆分後遇到的問題
默認情況下,模塊內部的state,mutations,getters,actions是註冊在全局命名空間的
- 多個倉庫子模塊中的getter
- 多個倉庫子模塊中的mutation如果同名的話,組件調用這個mutation,都會被觸發,會有被污染的危險
- 多個倉庫子模塊中的action,如果同名的話,組件調用這個action,都會被觸發,會有被污染的危險
3.解決問題
1.設置命名空間
給子模塊設置命名空間,在子模塊的對象中,設置namespaced屬性爲true
2.調用設置命名空間後的子模塊數據
//1.直接通過$store
this.$store.state.模塊名.xxx
//2.computed
computed:{
aaa(){
return this.$store.state.模塊名.xxx;
}
}
//3.mapState
computed:{
...mapState('xxxx',[state1,state2,state3])
}
//4.mapState的轉換
computed:{
state1(){
retrurn this.$store.state.xxxx.state1;
}
}
注意:如果要在組件中同時拿到多個倉庫中的子模塊的同名state數據,不要使用mapState.
3.調用設置命名空間後的某倉庫子模塊中的getter
//1 直接通過$store
this.$store.getters['xxxx/想要的數據']
//2.computed
computed:{
aaa(){
return this.$store.getters['xxxx/想要的數據']
}
}
//3.mapGetters
computed:{
...mapGetters('xxxx',[getter1,getter2])
}
//4.mapGetters的轉換
computed:{
getter1(){
return this.$store.getters['xxxx',getter1]
}
}
4.提交某個倉庫子模塊中的mutation
//1.直接通過$store
this.$store.commit('xxxx/某事件',payload)
//2.methods
methods:{
fn(payload){
this.$store.dispatch('xxxx/某事件',payload)
}
}
//3.mapActions
methods:{
...maActions('xxx',[action1,action2])
}
//4.mapActions的轉換
methods:{
action1(payload){
this.$store.dispatch('xxxx/action1',payload)
}
}
四.倉庫模塊的局部狀態
做了倉庫模塊的拆分後,getters與mutations中的第一個參數,是當前模塊的局部state,action中的第一個參數context,context中的state也是當前模塊的局部state
如果我們需要在getter中action中去獲取到其餘模塊的state數據,
1.getter語法
getters:{
//state 當前模塊的state
//getters 當前模塊的getters
//rootState 根模塊的state數據,根據它可以方便去拿其餘模塊的state
getter1(state,getters,rootState){
}
}
2.action語法
actions:{
//context 是個對象,這個對象中有些屬性
// state 當前模塊的局部state
// getters 當前模塊的局部getters
// commit 提交mutation的方法
// dispatch 派發action的方法
// rootState 跟模塊的state,可以獲取其他模塊的state
action1(context,payload){
}
}
注意:mutation沒有rootState
如果需要在mutation中使用其餘模塊的state數據
可以使用payload,比如在action中獲取到需要的rootState,然後作爲mutation的payLoad傳遞過去
五.v-model綁定倉庫中的數據情況
通過v-model綁定input框,v-model綁定倉庫中的數據.當我們在input框中輸入的時候,會報錯,也沒有引起倉庫中數據變化
其實這個現象的根本原因,還是倉庫中的state數據不允許直接修改,我們可以通過計算屬性中的get() ,set()方法來解決這問題
- 1.倉庫中需要提供一個mutation來處理變化
- 2.組件中給對應的computed提供一個getter,和setter
state:{
inputVal:"abc"
},
mutations:{
fn(state,payload){
state.inputVal=payload;
}
}
//組件上
computed:{
inputVal:{
get(){
return this.$store.state.inputVal;
}
//要修改依賴項提交mutations
set(value){
this.$store.commit('fn',value)
}
}
}
六. Vuex核心概念圖解
Vuex的主要包含3個東西,State,Actions,Mutations,首先呢,我們來看看這圖解的流程
Vuex裏有個倉庫,State,State裏的數據可以直接拿到組件中做一個Render渲染,如果我們要改變State倉庫裏的東西,可以直接從組件派發dispatch一個Actions,Actions是不能直接修改State倉庫的,只能提交Commit一個Mutation,然後在mutation中去修改State倉庫裏的數據.爲什麼只能用Mutations去修改呢,也是爲了更好的與Devtools更好的集成,裏面更好的利用Devtools的時間旅行機制.其實呢,我覺得還可以在Vue Components連一條線到Mutations上,因爲可以直接在組件上commit一個Mutation,當然了,如果是異步的話,還是經過Actions,一般我們獲取後臺接口數據的話,還是在Actions裏進行的.同步的話還是使用Mutations.
注意:倉庫中的state數據,不允許直接修改,只是一個規定,真正使用的話,是不會報錯的.但是不推薦.爲了更好的的處理報錯情況,所以state數據都是映射到組件的computed上.因爲computed裏的數據不能直接修改.