vuex——模塊化


一、什么是vuex module,為什么要使用vuex模塊化?

模塊化,就是將vuex分為不同的模塊,無論從項目上還是結構上,都容易維護,我們在平時寫的vuex中,都是在一個文件中,寫state、getters、mutations、actions。想象一下,如果我們的項目特別大,比如淘寶那么大,那么我們vuex中要維護的內容會特別多的時候,例如“購物車”需要用到vuex,“設置”需要用到vuex,“首頁”也需要用到vuex,那么如果我們都寫到一個文件中,就會出現代碼相當的“臃腫”。這一個store文件最后好幾萬行代碼。還怎么維護?

所以,我們vue官網就給出了辦法,使用vuex模塊化開發。

今天我們簡單學習使用,學會后,你要查閱官網,深入學習,才能提高這個技術。

模塊化有很多寫法,今天按照我的習慣,簡單的寫一下,我們和以前一樣,需要下載vuex,會得到一個store文件夾,內部我們有一個index跟文件。並且,我們需要自己創建一個modules文件夾,里邊放入我們想要區分的js模塊文件,你想分成多少個模塊,就分成多少個,我目前寫了倆個模塊,一個是購物車car.js,一個是我的my.js,type.js先不用管。如圖:

 

首先我們需要先將modules中的所有文件引入到index.js根文件中(以前我們是導出mutations等方法,現在這個文件中,我只引入了模塊,所以只需要導出模塊),如下(index.js):

import Vue from "vue";
import Vuex from "vuex";

// 引入兩個模塊文件
import car from './modules/car';
import my from './modules/my';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    car,
    my
  }
});

 然后我們就可以在每個模塊當中,寫入獨立的state、mutations等等。這樣我們在使用的時候,購物車就用car.js;我的就用my.js。用購物車car.js舉例(其他文件同理),如下(car.js):

const state = {

}

const getters = {

}

const mutations = {

}

const actions = {
    
}

export default {
    namespaced: true,
    state,
    getters,
    mutations,
    actions
}

這里就可以像以前一樣寫我們的vuex方法了。細心的同學會注意到,我們導出時,會多出一個namespaced:true,一般我們在模塊使用時,都會加入這個屬性。

命名空間:namesapced:true,當模塊被注冊后,它的所有getter、action及mutation都會自動根據模塊注冊的路徑調整命名,也就是說,我們在調用這些方法時,需要加上這個文件的路徑(比如我要訪問這個文件中的state里邊的某個屬性:this.$store.state.car。后邊這個car就是多了個car.js模塊名,因為如果不加模塊名,那我們會訪問所有模塊中的屬性,那就亂了),所以我們要加上命名空間,相當於獨立的區塊去使用,模塊和模塊之間互不干擾。

和平時一樣,我們跟個案例:

點擊增加數值(car.js):

const state = {
    number: 100
}

const getters = {

}

const mutations = {
    add(){
        state.number ++;
    }
}

const actions = {
    
}

export default {
    namespaced: true,
    state,
    getters,
    mutations,
    actions
}

我們重點說一下vue中怎么獲取模塊中的內容。我們可以和平常一樣,直接用this.$store.state.car.number來獲取到state中的number內容。我們今天說說在項目中最常使用的:輔助函數mapState、mapGetters、mapActions和mapMutations。

不一一舉例,簡單說兩個mapState和mapActions,深入理解可去看官網

我們在使用時,需要先引入:

import { mapState, mapActions } from 'vuex';

這兩個函數,前者寫在計算屬性computed中,后者寫在方法methods中。

在寫入時,需要用到展開符...,它可以將內容一一的展開。

舉個例子:

let a = [1, 2, 3];
let b = [4, 5, 6];
let c = [...a, ...b];
console.log(c);   // [1, 2, 3, 4, 5, 6]

那我們獲取一下state中的number:

computed: {
  ...mapState({
    a: state => state.car.number
  })
},
methods: {
  ...mapMutations(['car/add']),
  add(){
    this['car/add']()   // 注意,這里this后沒有點
  }
},

展開mapState,定義一個a,然后返回state中的car模塊下的number常量。展開mapMutations,返回是個數組,數組中是個字符串,返回car模塊下的add方法,定義一個add,直接觸發就可以。有人會問,觸發mutations中的方法不是應該用commit嗎,答案是我們用了mapMutations,它會將這個路徑直接映射成commit方法,所以我們直接用就行,這也是與原來的區別。

我們定義的這個a,就是想要的數值,可以在標簽中展示出來,add也直接使用。

<h2>{{a}}</h2>
<button @click="add">點擊增加</button>

這樣寫出來,是好用的,但是看起來會有問題。想一下,car是個模塊,我們現在只是舉例而已,但是如果我們在開發中,這個模塊下命名空間比較深入,還有其他模塊,一層一層比較多,就會變成這個樣子:

computed: {
    ...mapState({

      a: state => state.car.xx.xx.xx.number
      // 如果下邊還有很多,就要寫很多重復的 car.xx.xx.xx,如:
      b: state => state.car.xx.xx.xx.name
      c: state => state.car.xx.xx.xx.key
    })
  },

 methods: {
    ...mapMutations(['car/xx/xx/xx/add']),
    add () {
      this['car/xx/xx/xx/add']()
    }
  }

這個層層的嵌套,那就要寫很多重復的car/xx/xx/xx,所以我們可以,將這個模塊當作字符串提取出來,換個寫法,按照我們的舉例:

computed: {
  ...mapState('car', {
    a: state => state.number
  })
},
methods: {
  ...mapMutations('car', ['add']),
},

如上所示,我們可以將他作為參數,放到前面,這樣所有綁定都會自動將該模塊作為上下文,寫出來也簡單不少。當然我們還可以再簡化一些。我們可以通過使用createNamesapcedHelpers創建基於某個命名空間輔助函數。它返回一個對象,對象里有新的綁定在給定命名空間值上的組件綁定輔助函數。

就是我們可以從vuex中引入createNamespacedHelpers,然后將剛才的字符串作為參數,傳進來,如下:

// 這里引入createNamespacedHelpers
import { createNamespacedHelpers } from 'vuex';
// 定義mapState、mapMutations,並將car傳入createNamespacedHelpers
const { mapState, mapMutations } = createNamespacedHelpers('car');

computed: {
  ...mapState({
    a: state => state.number
  })
},
methods: {
  ...mapMutations(['add']),
},

這就是vuex模塊化,寫法都很多,看我們自己的習慣,當然了,我們在模塊中,還可以使用常量替代Mutation事件類型。在多人開發時,我們知道mutations中放入了方法,如果有很多方法,多人協作時找起來會比較麻煩,那我們可以創建一個放入常量的文件(前文中我們創建的type.js文件),在里邊我們可以定義常量,但注意的是,我們開發中習慣常量要大寫,單詞之間用下划線分開。並且,在模塊中引入這個文件:

一、首先,我們創建一個js文件,我們前文圖片中的type.js,在里邊創建一個常量,開發時前后要一致,並加以標注:

// 前后都要大寫,一般前后名稱一致,但是為了我們能夠理解,本次我們寫兩個
// 開發中,我們應該這樣寫:export const ADD_NUMBER = 'ADD_NUMBER'
// 本次我們定義前后不一樣的

export const ADD_NUMBER = 'AAA'   // 點擊增加數字

二、在car模塊中引入type.js並使用引入進來的常量:// 按需引入常量import { ADD_NUMBER } from './type';

const state = {
    number: 100
}

const getters = {

}

const mutations = {
    // 使用常量命名,注意,這里[ADD_NUMBER]映射出來的名稱,其實是AAA
    // 我們寫成固定的數字,也可以設置參數、靈活傳參
    // 第一個參數是state,第二個參數是傳入參數payload
    [ADD_NUMBER](state, payload){
        state.number += payload;
    }
}

const actions = {
    
}

export default {
    namespaced: true,
    state,
    getters,
    mutations,
    actions
}

  

三、vue頁面,由於剛才我們用了payload參數,所以我們也需要傳入參數,然后我們可以思考下,我們觸發的名稱應該寫哪一個?

methods: {
  // 思考一下問號的地方,應該寫 ADD_NUMBER還是AAA?
  ...mapMutations(['AAA']),
},

這個問題也就是我剛才故意在常量中,前后不一樣的原因,由於我們前后都寫一樣,有些小白會不知道,這里定義的到底是前邊的名稱,還是后邊字符串的名稱。答案是AAA,也是ES6中對象的擴展寫法。

最后的寫法是這樣的:

<h2>{{a}}</h2>
<button @click="aaa(2)">點擊增加</button>

computed: {
  ...mapState({
    a: state => state.number
  })
},
methods: {
  // 思考一下問號的地方,應該寫 ADD_NUMBER還是AAA?
  // ...mapMutations(['AAA']),
  
  // 我們除了可以寫成數組,還可以用對象的寫法
  ...mapMutations({
    aaa: 'AAA'
  })

  // 你可以按照原始寫法寫,當然要去掉標簽中的參數,參數改成下邊傳遞。
  // aaa(){
  //   this.$store.commit('car/AAA', 100);
  // }

},

這就是modules模塊化的開發寫法,希望看完,你們會有所收獲。

 來源:https://yq.aliyun.com/articles/738863


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM