如何使用Vuex


npm install vuex --save-dev //安裝vuex
// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.store({
	state:{

	},
	mutation:{

	},
	action:{

	},
	getter:{

	},
	module:{

	}
})

export default store


// main.js
import store from './store'

new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})

Vuex.store需要傳入的各個屬性:

state

state封裝Vuex需要管理的狀態;
單一狀態樹(不建議new兩個或以上的store)

//例子:
const store = new Vuex.store({
	state:{
		counter:1000
	},
	...
})


//訪問state中的狀態
{{ $store.state.counter }}

//修改state中的狀態
"$store.state.counter++"  //不建議直接修改,直接修改儘管也是響應式的,
						  //但是這樣的修改方式無法被devtools追蹤到,不便於後期的調試
//那麼應該怎樣修改?

首先看一幅圖:
在這裏插入圖片描述
這是官方建議的修改方式,我們從最下方的紫色的State開始看起,State藉由Render可以在Vue Components上進行展示,而Vue Components需要通過分配Actions,然後commitMutations,最後通過Mutations的Mutate行爲來修改State。

可以看到,在Mutations處向外延伸連接到了一個Devtools,這是一個Vue官方的瀏覽器插件,它的作用正是追蹤修改,保存修改記錄的。

那麼爲什麼不直接從Vue Components指向Mutations呢?爲什麼還要再多走一步Actions呢?

這裏要區分清楚,其實從Vue Components指向Mutations也是可以的,只是這樣的修改方式只適用於同步操作,如果是異步操作的話,就必須要經過Actions,否則的話Devtools將追蹤不到異步操作的記錄。

從圖中可以清楚的看到,Actions通過Backend API將異步操作轉換爲同步操作,之後再傳入到Mutations,這樣就能被Devtools追蹤到了。

需要注意的是,Devtools是一個瀏覽器插件,使用之前需要先在瀏覽器上安裝。

所以如果是同步操作的話,正確的修改方式是:

const store = new Vuex.store({
	state:{  //定義狀態
		counter:1000
	},
	mutations:{  //定義方法
		increment(state){  //默認參數state
			state.counter++
		},
		decrement(state){
			state.counter--
		}
	},
	...
})

this.$store.commit('incremnet')  //通過這種方法調用mutations中定義的方法
this.$store.commit('decremnet')  

getters

getters類似於一個計算屬性,當我們需要獲取state中的一些變異數據,並且這種數據多個組件都需要用到時,推薦使用getters。

const store = new Vuex.store({
	state:{  
		counter:1000
		students:[
			{id:100,name:'Jack'},
			{id:101,name:'Tom'},
			{id:102,name:'Jane'}
		]
	},
	getters:{
		getPowercounter(state){  //默認第一個參數爲state
			return state.counter * state.counter
		},
		getIdgt101(state){  //獲取id大於101的學生
			return state.students.filter(s => s.id > 101)
		},
		getIdgt101Length(state,getter){  //獲取id大於101的學生的數量,這裏可傳入第二個默認參數getters
			return getter.getIdgt101.length
		},
		getIds(state){  //獲取id大於指定id的學生,不能在這裏傳入id,第二個參數傳入的不管是什麼都被指向getters
			return id => {
				return state.students.filter(s => s.id > id)
			}
		}
	}
	...
})

$store.getters.getIdgt101  //調用getter中的方法
$store.getters.getIds(100)

mutations

Vuex官方指定,對狀態的更改必須要經過mutations,這裏要注意區分getters與mutations,getters是對狀態的異變但這種異變不會作用於state中,即狀態本身是沒有改變的,只是呈現出來的變了,而mutations是改變了state中的狀態。

mutations:{
	increment(state){  //默認傳入state參數

	},
	increment(state,count){  //需要傳入其它參數時,放在後面

	},
	increment(state,obj){  //傳入多個參數時,以對象的形式放在state後面

	}
}

//調用
//風格1
$store.mutations.commit('increment')
$store.mutations.commit('increment',count)
$store.mutations.commit('increment',obj)

//風格2
$store.mutations.commit({
	type:'increment',
	count   //注意這裏的count傳入mutations中的increment()方法後是作爲對象形式傳入的,即應該payload.count這樣訪問
})

Vuex的響應式注意點

Vuex中管理的狀態都是響應式的,但這要有一個前提條件,即這些狀態是提前已經定義的,是已經初始化過的並封裝在state中的,比如說:

state:{
	info:{name:'lihua',age:18}
}

這個info當然是響應式的,我們對info中的數據即name和age不管做什麼更改都會立即呈現在頁面上,但如果我們想要往info中添加一個新屬性,你就會發現,屬性雖然在後臺確實添加進了info中,但它不是響應式的,這是因爲新屬性並沒有事先被定義,所以它不會被添加到Vue的響應式系統中。

那麼這時,我們又確實希望這種行爲也能是響應式的,那麼該怎麼辦呢?

方法如下:

Vue.set(state.info,grade,2018)  //響應式的添加一個新屬性
Vue.delete(state.info,name)  //響應式的刪除一個屬性

actions

如果是同步操作,那麼直接經由mutations修改狀態就可以,但如果是異步操作,之前已經提到,需要先經過actions的一層包裝之後,再經由muations修改狀態,否則devtools將追蹤不到異步操作。

具體用法參考如下:

mutations:{
	updateinfo(state):{
		state.info.name = 'xiaoming'
	}
},
actions:{
	unpadeInfo(context){  //這裏也有默認參數,但是context,不是state,context相當於store
		setTimeout(() => {
			context.commit('updateinfo') //這裏commit的是mutations中的方法
		},1000)
	}
}

//調用
$store.actions.dispatch('updateInfo')

需要傳入參數時,參照:

mutations:{
	updateinfo(state):{
		state.info.name = 'xiaoming'
	}
},
actions:{
	unpadeInfo(context,payload){   //定義第二個參數接受傳入的參數,對象類型
		setTimeout(() => {
			context.commit('updateinfo')
			...  //操作payload
		},1000)
	}
}

$store.actions.dispatch('updateInfo',message)  //在這裏傳入參數

另外,因爲actions中封裝了一步方法,當我們需要在異步方法中定義回調時,參考如下:

mutations:{
	updateinfo(state):{
		state.info.name = 'xiaoming'
	}
},
actions:{
	unpadeInfo(context,payload){   
		return new Promise((resolve,reject) => {
			setTimeout(() => {
				context.commit('updateinfo')
				...  //操作payload
				resolve() //調用resolve
			},1000)
		})
	}
}

$store.dispatch('updateInfo',message)
	.then(() => {
		...  //回調函數
	})

modules

modules的作用是給Vuex分塊,當Vuex管理的狀態過多而導致代碼或者邏輯混亂時,我們可以在modules中定義新的模塊,這些模塊與store類似但作爲store的一部分,如下:

const store = new Vuex.store({
	state:{},
	mutations:{},
	actions:{},
	getters:{},
	modules:[
		VuexA:{  //VueA模塊
			state:{},
			mutations:{},
			actions:{},
			getters:{},	
		},
		VuexB:{
			...
		},
		...
	}
})

//訪問Vuex中的state
$store.state.Vuex.***

//對於模塊內部的 mutation 和 getter,接收的第一個參數是模塊的局部狀態對象。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章