1.什么是狀態:
可以理解為在data中的屬性需要分享給其他vue組件使用的部分,就叫做狀態。簡單的說就是data中需要共有屬性。
例如:在中大型項目中會有很多共用的數據。我們有幾個頁面同時顯示用戶的名稱和用戶等級,如果不把這些屬性設置為狀態,那每個頁面遇到后,都會到服務器進行查找計算,返回后再顯示。這樣消耗大量性能,得不償失,而vuex是一個很好的解決方法。
2.安裝
·npm install vuex --save/cnpm install vuex --save
3.引入
·import Vue from 'vue'
·import Vuex from 'vuex'
Vue.use(Vuex);
4.實例
·現在我們新建store.js文件,在里面增加一個常量對象。store.js文件就是我們引入vuex時的那個文件。
const state={
? ? count:1
}
·用export default封裝代碼,讓外部可以引用
export default new Vuex.Store({
? ? state
})
·新建一個vue的模版,位置在components文件夾下,名字叫count.vue,在模版中我們引入我們剛建的store.js文件,并在模版中用$store.state.count輸出count的值。
<template>
<div>
<h2>{{msg}}</h2><hr/>
<h3>{{$store.state.count}}</h3>
</div>
</template>
<script>
import store form '@/vuex/store'
export default{
? ? data(){
? ? ????return{
? ? ????????msg:'Hello Vuex',
????????}
????},
store
}
</script>
·在store.js文件中加入兩個改變state的方法
const mutations={
? ? state.count++;
},
reduce(state){
? ? state.count--;
}}
注:這里的mutations時固定的寫法,意思是改變的,要改變state的數值的方法必須寫在mutations里。
·在count.vue模版中加入兩個按鈕,并調用mutations中的方法
<div>
? ? <button @click="$store.commit('add')>+????</button>
? ? <button @click="$store.commit('reduce')">-</button>
</div>
注:這樣進行預覽就可以實現對vuex中的count進行加減了。
·將狀態對象賦值給內部對象,也就是把stroe.js中的值賦值給我們模版中data中的值(讀取數據)。三種方法:
1)通過computed的計算屬性直接賦值
注:computed屬性可以在輸出前,對data中的值進行改變,我們就利用這種特性把store.js中的state值賦值給我們模版中的data值。
computed:{
? ? ????count(){
? ? ? ? ? ? return this.$store.state.count; ? ?
????????}????
}
注:這里需要注意的是return this.$state.count這一句,一定要寫this,不然找不到$store。這種方法很好理解,寫起來復雜。
2)通過mapState的對象來賦值
我們首先要用import引入mapState:
import {mapState} from 'vuex';
然后還在computed計算屬性里寫如下代碼:
computed:mapState({
? ? count:state=>state.count
})
注:這里我們使用ES6的箭頭函數來給count賦值
3)通過mapState的數組來賦值:
? ? computed:mapState([""count])
注:這個算是最簡單的寫法,在實際項目開發中也經常這樣使用。
·Mutations修改狀態(修改數據)
·$store.commit()
Vuex提供commit方法來修改狀態,我們在button上修改方法:
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('reduce')">-</button>
·store.js 文件:
? ? const mutations={
? ? ????? ? ? ? add(state){
? ? ? ? ? ? ? ? state.count++;
????????},
? ? reduce(state){
? ? ? ? state.count--;
????}
}
·傳值:這只是一個最簡單的修改狀態的操作,在實際項目中我們常常需要在修改狀態時傳值。比如上邊的例子,是我們每次只加1,而現在我們要通過所傳的值進行相加。只需要在Mutations里再加上一個參數,并在commit的時候傳遞。
注意:現在store.js文件里給add方法加上一個參數n。
? ? const mutations={
? ? ? ? ? add(state,n){
? ? ? ? ? ? state.count+=n;
????},
? ? reduce(state){
? ? ? ? state.count--;
????}
}
·在Count.vue里修改按鈕commit()方法傳遞的參數,我們傳遞10;意思是每次加10
<p>
? ??<button @click="$store.commit('add',10)">+</button>
<button @click="$store.commit('reduce')">-</button>
</p>
注:這樣兩個簡單的修改我們就完成了傳值。
·模版獲取Mutations方法
實際開發中我們也不喜歡看到$store.commit()這樣方法出現,希望跟調用模版里的方法一樣調用
例如:@click="reduce"就和沒引用vuex插件一樣
要達到這種寫法,只需要兩步:
1)在模版count.vue里用import引入我們的mapMutations:
import {mapState,mapMutations} from 'vuex';
2)在模版的<script>標簽里添加methods屬性,并加入mapMutations
methods:mapMutations({
? ? 'add','reduce'
})
通過上面兩步,我們已經可以在模版中直接使用我們的reduce或者add方法,就像下面:
<button @click="reduce">-</button>
·getters計算過濾操作
getters從表面是獲取的意思,可以把他看作在獲取數據之前進行的一種再編輯,相當于對數據的一個過濾和加工。也可以看作是store.js的計算屬性。
·比如我們現在要對store.js文件中的count進行一個計算屬性的操作,就是在它輸出前,給它加上100。首先在store.js里用const聲明getters屬性。
const getters={
? ? count:function(state){
? ? ? ? return state.count +=100;
????}
}????
寫好getters之后,我們還需要在Vuex.Store()引入,由于已經引入了state和mutations,所以引入里有三個引入屬性:
export default new Vuex.Store({
? ? state, mutations,getters
})
在store.js里的配置算是完成,需要到模版頁對computed進行配置。在vue的構造器里邊只能有一個computed屬性,如果寫多個,只有最后一個computed屬性可用,所以要改造上邊computed屬性。改造時使用ES6的展開運算符“...”。
computer:{
? ? ...mapState(["count"]),
? ? count(){
? ? ? ? return this.$store.getters.count;
????}
}
注:寫配置時,在每次count的值發生變化的時候,都會進行加100的操作。
·用mapGetters簡化模版寫法:
state和mutations都有map的引用方法把模版中編碼進行簡化,getters也有:
`首先用import引入mapGetters:
import {mapState,mapMutations,mapGetters} from 'vuex';
`在computed屬性中加入mapGetters
...mapGetters(["count"])
·actions異步修改狀態
actions和之前講的Mutations功能基本一樣,不同點是actions是異步的改變state狀態,而Mutations是同步改變狀態。
注:在store.js聲明action是可以調用Mutations里的方法里,下面在actions里調用add和reduce兩個方法:
const actions = {
? ? addAction(context){
? ? ? ? context.commit('add',10)
????},
? ? reduceAction({commit}){
? ? ? ? ? ? commit('reduce')
????????}
}
注:在actions里寫了兩個方法addAction和reduceAction,在方法體里,用commit調用了Mutations里邊的方法。兩個方法傳遞的參數不一樣。
·context:上下文對象,這里理解為store
·{commit}:直接把commit對象傳遞過來,可以讓方法體邏輯和代碼更清晰明了
·模版中的使用
需要在count.vue模版中編寫代碼,讓actions生效。先復制兩個上面按鈕,并改成我們的actions里的方法名,分別是:addAction和reduceAction:
<p>
? ? <button @click="addAction">+</button>
? ? <button @click="reduceAction">-</button>
</p>
改造一下methods方法,首先還是用擴展運算符把mapMutations和mapActions加入:
methods:{
? ? ...mapMutations([
? ? ? ? 'add','reduce'
? ? ]),
? ? ...mapActions(['addAction','reduceAction'])
},
注:記得用import把mapAction引入才可以使用。
·增加異步體驗
現在看到的效果和用Mutations一模一樣,那么action有什么用,加一個計時器(setTimeOut)延遲執行。在addAction里使用setTimeOut進行延遲執行:
setTimeOut(()=>{context.commit(reduce)},3000);
console.log('我比reduce提前執行');
可以看到在控制臺先打印出了‘我比reduce提前執行’這句話。
·module模塊組
隨著項目的復雜性增加,共享的狀態越來越多,這時候需要把狀態的各種操作進行一個分組,分組后再進行按組編寫(狀態管理器的模塊化組操作)
·聲明模塊組:
在vuex/store.js中聲明模塊組,用const常量方法聲明模塊組:
const moduleA={
? ? state, mutations,getters,actions
}
聲明好后,修改原有Vuex.Stroe里的值:
export default new Vuex.Store({
? ? modules:{a:moduleA}
})
·在模版中使用,用插值的形式寫入:
<h3>{{$store.state.a.count}}</h3>
·如果想用簡單的方法引入,可以用計算屬性中return我們的狀態:
computer:{
? ? count(){
? ? ? ? return this.$store.state.a.count;
????}
}