原創 Vue個人查漏補缺筆記day13 -- Vuex基礎使用(state、mutations、actions、getters、module、nameSpaced)

ELNino_Thomas.Liang發表於2021-01-04

為什麼會有Vuex

Vuex是轉為vue應用程式開發的狀態管理模式,採用集中式儲存管理應用的所有元件的狀態

  • 作用:採用集中式管理元件依賴的共享資料,解決不同元件資料共享

主要組成

  • state:共享狀態資料
  • mutations:修改狀態資料,且只執行同步程式碼操作
  • actions:執行非同步操作,提交給mutations修改狀態資料
  • getters:處理state中的資料
  • module:實現Vuex模組化

state/mutations/actions/元件間的關係

在這裡插入圖片描述


初始使用Vuex

//在腳手架的main.js檔案中
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'

Vue.use(Vuex)

//例項化Vuex
const store = new Vuex.store({
//在這裡定義state/mutations/actions等,且均為物件形式
	state:{},
	mutations:{},
	actions:{}
})

new Vue({
  render: h => h(App),
  //注入Vuex
  store
}).$mount('#app')



state使用

state是放置公共狀態的屬性
定義state

//main.js
const store = new Vuex.store({
//在這裡定義state/mutations/actions等,且均為物件形式
	state:{
		num:0
	}
})

//test.vue
//在元件中獲取vuex的state狀態資料 有兩種方法
//1.通過$store(掛載到Vue中接收Vuex.store的常量名).state獲取
//$store.state.num
//2.通過Vuex提供的輔助方法 mapState 獲取
//import {mapState} from 'vuex',然後在computed屬性中定義
<template>
	<div>原始方法拿count:{{ $store.state.num }}</div>//0
	<div>用computed方法拿num:{{ getNum }}</div>//0
	<div>用輔助函式+computed方法拿num:{{ num }}</div>//0
</template>

<script>
import { mapState} from "vuex";
export default {
	computed: {
		...mapState(["num"]),
		getNum(){
			return this.$store.state.num
		}
	}
};



mutations使用

state資料的修改只能通過mutations,並且mutations必須是同步更新

  • 定義mutations
//main.js
const store = new Vuex.store({
//在這裡定義state/mutations/actions等,且均為物件形式
	state:{
		num:0
	},
	mutations:{
		// 方法裡引數 第一個引數是當前store的state屬性
		addNum(state){
			state.num ++
		},
		//第二個引數是載荷 運輸引數 呼叫mutaiions的時候 可以傳遞引數 傳遞載荷
		numPlusVar(state,var){
			state.num += var
	}
})


//使用
//test.vue
//mutations修改vuex的state狀態資料 有兩種方法,類似於state
//1.通過$store.commit('方法名')方法獲取
//2.通過Vuex提供的輔助方法 mapMutations獲取
//import  {mapMutations } from 'vuex',然後在methods屬性中定義
//如果是帶參的,則在方法後面傳參即可
<template>
	<div>{{ num }}</div>//0
	<button @click="numAdd1">用commit方法+1</button>
	<button @click="numAddVar">用commit方法傳參修改</button>
	<button @click="addNum">用mapMutations方法+1</button>
	<button @click="numPlusVar(100)">用mapMutations方法傳參修改</button>
</template>

<script>
import { mapState,mapMutations } from "vuex";
export default {
	methods:{
	//方法1
		numAdd1(){
			this.$store.commit('addNum')
		},
		numAddVar(){
			this.$store.commit('numPlusVar',100)
		},
	//方法2 -- mapMutations 傳入陣列,定義函式
	...mapMutations(['addNum','numPlusVar'])
	},
	computed: {
		...mapState(["num"])
	}
};



actions使用

mutations是同步更新資料,actions則負責進行非同步操作

  • 定義actions
//main.js
const store = new Vuex.store({
//在這裡定義state/mutations/actions等,且均為物件形式
	state:{
		num:0
	},
	mutations:{
		numPlusVar(state,var){
			state.num += var
		}
	},
	actions:{
		//  獲取非同步的資料 第一個引數context表示當前的store的例項 可以通過 context.state 獲取狀態 也可以通過context.commit 來提交mutations, 也可以 context.diapatch呼叫其他的action
		asyncAddNum(context,var){
			 setTimeout(function(){
     	 	  // 一秒鐘之後 去修改state中的num,帶參
     	 	  context.commit('numPlusVar', var)
 		     }, 1000)
		}
	}
})

//使用
//有兩種方式
//1.通過$store.dispatch('方法名')來使用
//2.通過輔助函式mapActions來使用
//import { mapActions } from 'vuex',然後在methods中定義
<template>
	<div>{{ num }}</div>//0
	<button @click="asyncChange">用原始dispacth方法非同步修改</button>
	<button @click="asyncAddNum(100)">用mapActions方法非同步修改</button>//一秒後+100
</template>


<script>
import { mapState,mapActions } from "vuex";
export default {
	computed: {
		...mapState(["num"])
	},
	methods:{
		//方法1
		asyncChange(){
			//一秒後+10
			this.$store.dispatch('asyncAddNum',10)
		},
		//方法2
		...mapActions(['asyncAddNum'])
	}



getters使用

除了state之外,有時我們還需要從state中派生出一些狀態,這些狀態是依賴state的,此時會用到getters
例如:state中有陣列list:[0,1,2,3,4,5,6,7,8,9],但只想要其中大於3的數值,如果不用getters,那麼就需要先獲取再修改,而getter可以先處理資料,再通過返回值返回資料

  • 定義getters
//main.js
const store = new Vuex.store({
	state:{
		list:[0,1,2,3,4,5,6,7,8,9]
	},
	getters:{
		   // getters函式的第一個引數是 state
  		  // 必須要有返回值
  		  //採用es6的簡寫
  		  listFilter:state => state.list.filter(item => item > 3)
	}
})

//使用
//兩種方法,類似於state
//1.通過$store.getters.函式名,或是在computed中定義
//2.通過輔助函式mapGetters

<template>
	<div>原始方法{{ $store.getters.listFilter }}</div>//[4,5,6,7,8,9]
	<div>原始方法+computed{{ filtedList }}</div>//[4,5,6,7,8,9]
	<div>mapActions方法{{ listFilter }}</div>//[4,5,6,7,8,9]
</template>


<script>
import { mapActions } from "vuex";
export default {
	computed: {
		filtedList(){
		//方法1
			return this.$store.getters.listFilter 
		},
		//方法2
		...mapActions(['listFilter'])
	},
</script>



module使用

由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的物件。當應用變得非常複雜時,store 物件就有可能變得相當臃腫。簡而言之:如果把所有的狀態都放在state中,當專案變得越來越大的時候,Vuex會變得越來越難以維護,由此,又有了Vuex的模組化
原理:
在這裡插入圖片描述

假如: 有兩個模組,user模組用來儲存token,setting模組用來儲存使用者名稱username

  • 定義模組
//main.js
const store  = new Vuex.Store({
  modules: {
    user: {
       state: {
         token: '12345'
       }
    },
    setting: {
      state: {
         name: 'Thomas'
      }
    }
  })


//在模組裡面的state是全域性vuex可用的,所以獲取有兩種方法
//1.通過$store.state.模組名稱.模組中的state名稱
//$store.state.user.token / $store.state.setting.name
//2.通過store中的根getters來定義
 getters: {
   token: state => state.user.token,
   name: state => state.setting.name
 } 

//使用
<template>
	<div>原始方法{{ $store.state.user.token }}</div>//'12345'
	<div>mapGetters方法{{ token }}</div>//'12345'
	<div>mapGetters方法{{ name }}</div>//'Thomas'
</template>

<script>
import { mapGetters } from "vuex";
export default {
	computed: {
		//方法2
		...mapGetters(['token','name'])
	},
</script>



名稱空間 – namespaced

預設情況下,module模組內部的 action、mutation 和 getter 是註冊在全域性名稱空間的——這樣使得多個模組能夠對同一 mutation 或 action 作出響應。
簡而言之:模組之間的 action、mutation 和 getter 其實並沒有區分,都可以直接通過全域性的方式呼叫
在這裡插入圖片描述
例如:

  modules: {
    user: {
       state: {
         token: '12345'
       },
       mutations:{
       	 //  這裡的state表示的是user的state
         updateToken (state) {
            state.token = '6789'
       }
    },
}

<template>
	<div>{{ $store.state.user.token }}</div>//'12345'
	<button @click='updateToken'>修改token</button>
</template>

<script>
import { mapMutations } from "vuex";
export default {
	methods:{
		...mapMutations(['updateToken'])//修改module中user的token
	}
}
</script>

但是,如果我們想保證內部模組的高封閉性,我們可以採用nameSpaced:true來進行設定

 modules: {
    user: {
    	nameSpaced:true,//名稱空間
      	state: {
         token: '12345'
       },
       mutations:{
       	 //  這裡的state表示的是user的state
         updateToken (state) {
            state.token = '6789'
       }
    },
}

//此時,元件中的	...mapMutations(['updateToken'])將會失效

如果需要使用名稱空間中的mutations
方法1:mapMutations帶上模組名

...mapMutations(['user/updateToken']),
changeToken(){
	this['user/updateToken']()
}

//template
<button @click='changeToken'>修改token</button>

方法2:使用輔助函式createNamespacedHelpers來建立基於某個名稱空間輔助函式

import {  createNamespacedHelpers } from 'vuex' //引入輔助函式
const { mapMutations } = createNamespacedHelpers('user') // 拿到模組user,然後拿到user中的mutations 
//相當於 const mapMutations =  createNamespacedHelpers('user').mutations 
export default {
	methods:{
		...mapMutations(['updateToken ']) //user中的mutations
	}
}

<div>{{$store.state.user.token}}</div>
<button @click="changeToken">用createNamespacedHelpers來呼叫名稱空間中的mutations</button>

相關文章