Vuex的初探與實戰小結

1.概述

每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)。

Vuex 和單純的全局對象有以下兩點不同:

1.Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地得到高效更新;2.你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用

**2.安裝使用 **

2.1.使用Vue-cli開發安裝vue包

cnpm install vuex --save

2.2.在src目錄下創建store文件夾並創建index.js如下(src/store/index.js)

import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex);
 
export default new Vuex.Store({
 state: {
 
 },
 getters: {
 
 },
 mutations: {
 
 },
 actions: {
 
 }
});

前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。

然後在src文件下的main.js中使用

import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
 
 
new Vue({
 el: '#app',
 store,
 components: { App },
 template: '<App/>'
})

3.用法簡介

** 3.1.state**

state是保存共享數據的,現在改store/index.js如下:

state: {
  count:0
 },

在components目錄下創建Index.vue如:

<template>
 <div class="index">
  {{count}}
 </div>
</template>
 
<script>
 export default {
  name: "index",
  computed:{
   count(){
    return this.$store.state.count;
   }
  }
 }
</script>

前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。

結果如下:



我們可以通過組件的計算屬性來保存state裏面的值,那麼問題來了,如果store太多的話,我們組件裏面的計算屬性豈不是成了這個樣子:

computed:{
 count(){
   return this.$store.state.count;
 },
  stateA(){
   return this.$store.state.stateA;
  },
  stateB(){
   return this.$store.state.stateB;
  }
}

這樣獲取共享狀態的數據也沒有什麼問題不過看起來還是有大量的重複冗餘代碼,我們可以使用 mapState 輔助函數幫助我們生成計算屬性,讓你少按幾次鍵:

當映射的計算屬性的名稱與 state 的子節點名稱相同時,我們也可以給mapState傳一個字符串數組。

import {mapState} from 'vuex'
 export default {
  name: "index",
  computed:{
   ...mapState(['count']),
  }
 }

小結:使用 Vuex 並不意味着你需要將所有的狀態放入 Vuex。雖然將所有的狀態放到 Vuex 會使狀態變化更顯式和易調試,但也會使代碼變得冗長和不直觀。如果有些狀態嚴格屬於單個組件,最好還是作爲組件的局部狀態。

3.2.getter

有的時候我們需要對共享狀態裏面的某一個屬性做一些處理後再使用,我們可以把數據獲取後再在組件的計算屬性中處理,舉個例子如下:

// store/index.js
state: {
  count:0,
  numbers:[0,1,2,3,4,5,6,7,8]
 },
// Index組件
<template>
 <div class="index">
  {{count}}
  <br>
  {{numbers.join()}}
 </div>
</template>
<script>
 import {mapState} from 'vuex'
 export default {
  name: "index",
  computed:{
   ...mapState(['count']),
   numbers(){
    return this.$store.state.numbers.filter((item)=>{
     return item>3;
    })
   }
  }
 }
</script>

前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。

結果如下:



那麼問題來了,如果多個組件都要做同樣的處理,我們就需要把一份代碼複製到多個地方,顯然是不大合理的,於是有了getter,可以理解爲組件裏面的計算屬性。示例如下:

/ store/index.js
getters: {
  filterNumbers(state){
   return state.numbers.filter((item)=>{
    return item>3;
   })
  }
 },
// Index組件
<template>
 <div class="index">
  {{count}}
  <br>
  {{filterNumbers.join()}}
 </div>
</template>
 
<script>
 import {mapState} from 'vuex'
 export default {
  name: "index",
  computed:{
   ...mapState(['count']),
   filterNumbers(){
    return this.$store.getters.filterNumbers;
   }
  }
 }
</script>

結果完全一樣,我們可以根據this.$store.getters.屬性名來獲取getters,也可以通過 mapGetters 輔助函數將 store 中的 getter 映射到局部計算屬性:

具體實現方式如下:

<template>
 <div class="index">
  {{count}}
  <br>
  {{filterNumbers.join()}}
  <br>
  {{antherNumbers.join()}}
 </div>
</template>
 
<script>
 import {mapState,mapGetters} from 'vuex'
 export default {
  name: "index",
  computed:{
   ...mapState(['count']),6
   ...mapGetters(['filterNumbers']),
   ...mapGetters({
    antherNumbers:'filterNumbers'
   })
  }
 }
</script>

如果用同一名字直接把數組作爲參數,如果想改一個名字,可以傳入一個對象作爲參數,結果如下:


3.3.mutation

在組件內,來自store的數據只能讀取,不能手動改變,改變store中數據唯一的途徑就是顯示的提交mutations。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作爲第一個參數。改變代碼如下:

// store/index.js
mutations: {
 add(state){
  state.count++;
 }
},
 
// Index組件
**
  <button @click="add">+</button>
**
  methods:{
   add(){
    this.$store.commit('add');
    console.log(this.count);
   }
**

連續點擊5次增加按鈕,發現count的值也改變了。當然,我們也可以傳參進去

// store/index.js
mutations: {
 add(state,n){
  state.count+=n;
 }
},
 
// Index組件
**
  <button @click="add">+</button>
**
  methods:{
   add(){
    this.$store.commit('add',10);
    console.log(this.count);
   }
**

觸發方法語句爲:this.$store.commit(方法名);也可以使用輔助函數mapMutations代替:

methods:{
  ...mapMutations(['add']),
}

3.4.action

前面我們講過,mutation有必須同步執行這個限制,我們在業務需求中有時候需要在獲取ajax請求數據之後再操作或定時器操作數據,這些都屬於異步請求,要用actions來實現。具體實現如下:

// store/index.js
mutations: {
  changeCount(state){
   state.count=3000;
  },
 },
 actions: {
  changeCount3000s(context){
   setTimeout(()=>{
    context.commit('changeCount')
   },3000)
 
// Index組件
<button @click="changeCount3000s">點擊按鈕3s後count的值改變</button>
methods:{
 ...mapMutations(['add']),
  changeCount3000s(){
    this.$store.dispatch('changeCount3000s');
  }
 }

前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,羣內有大量PDF可供自取,更有乾貨實戰項目視頻進羣免費領取。

我們在點擊按鈕3s後count的值改變爲3000,我們可以通過this.$store.dispatch(方法名)來觸發事件,也可以通過輔助函數mapActions來觸發。

import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
  methods:{
   ...mapMutations(['add']),
   ...mapActions(['changeCount3000s'])
  }

學會以上幾個屬性的使用基本就可以滿足平時業務中的需求了,但使用Vuex會有一定的門檻和複雜性,它的主要使用場景是大型單頁面應用,如果你的項目不是很複雜,用一個bus也可以實現數據的共享,但是它在數據管理,維護,還只是一個簡單的組件,而Vuex可以更優雅高效地完成狀態管理,所以,是否使用Vuex取決於你的團隊和技術儲備。

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