Vuex狀態管理(下)

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裏的數據不能直接修改.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章