首先什么是vuex,官網(wǎng)的解釋是狀態(tài)管理模式、集中式存儲(chǔ)管理
什么是狀態(tài)管理模式:
狀態(tài)即決定視圖表現(xiàn)的數(shù)據(jù),比如我們會(huì)在組件的data中定義一個(gè)numbe:1,那么我們就可以在組件中顯示該數(shù)據(jù),在Vuex中就被稱為狀態(tài)。一個(gè)組件中會(huì)定義很多個(gè)狀態(tài),這個(gè)時(shí)候就需要分類管理了,比如一個(gè)班級(jí)下面會(huì)有人數(shù),性別等狀態(tài),如果把班級(jí)當(dāng)作一個(gè)文件夾,那個(gè)人數(shù),性別等狀態(tài)就是該文件夾下面的文件,就出現(xiàn)了層級(jí)關(guān)系,這個(gè)就是狀態(tài)樹。
什么是集中式存儲(chǔ)管理:
集中即代表不是分散的,不是各個(gè)組件單獨(dú)維護(hù)自己的狀態(tài)(在組件中使用 data配置項(xiàng)聲明),而是集中管理,可以理解為一種響應(yīng)式的全局變量,準(zhǔn)確來(lái)說(shuō)是要求應(yīng)用建立并維護(hù)一個(gè)單一的、全應(yīng)用范圍共享的狀態(tài)樹
什么時(shí)候要用到vuex:
vue里面是由一個(gè)又一個(gè)組件組成的,所以就存在組件中的通信,組件的通信有很多方法,但是如果不是簡(jiǎn)單的父子組件的通信,而是一個(gè)狀態(tài)需要共享給多個(gè)組件時(shí),就會(huì)非常麻煩,數(shù)據(jù)也會(huì)相當(dāng)難維護(hù)
什么是狀態(tài)庫(kù):
Vuex的Store類 —— 狀態(tài)庫(kù) —— 用于管理狀態(tài)樹,它的實(shí)例化配置項(xiàng)state 用來(lái)聲明要?jiǎng)?chuàng)建的狀態(tài)樹,代碼如下:
const store = new Vuex.Store({
state:{ numner:0 }//state:存儲(chǔ)狀態(tài)。也就是變量
})
如何使用狀態(tài)庫(kù):
為了避免每個(gè)組件都要引入,我們可以在vue實(shí)例化的時(shí)候?qū)顟B(tài)庫(kù)掛接為Vue實(shí)例的一個(gè)屬性上
new Vue({
store:store, //使用store配置項(xiàng),就可以將狀態(tài)庫(kù)掛接為Vue實(shí)例 的屬性$store
template:'<ez-counter/>',
components:{EzCounter}
})
如何訪問state里面的狀態(tài):
使用計(jì)算屬性
computed: {
number () {
return this.$store.state.number
}
},
引入輔助函數(shù)mapState
//這里的state => state.number是es6里面的箭頭函數(shù)相當(dāng)于
//function(state) {
// return state.number
//}
import { mapState } from 'vuex';
export default {
computed: {
...mapState({
number : state => state.number ,
number 1: state => state.number1
})
},
如果state里面定義的字段和頁(yè)面要顯示的字段是一樣的話,也可以寫成數(shù)組模式
...mapState([
'number ',
'number 1'
])
什么時(shí)候使用getter:
getter:官方的解釋是可復(fù)用的計(jì)算屬性 —— 派生狀態(tài),說(shuō)明白了也就是對(duì)state里面狀態(tài)的進(jìn)一步操作,比如數(shù)組的排序,過濾等,當(dāng)多個(gè)組件需要這個(gè)功能的時(shí)候可以進(jìn)行復(fù)用,可以理解為一個(gè)全局的公用函數(shù),官方的例子如下:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
//對(duì)列表進(jìn)行過濾
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
},
//Getter 也可以接受其他 getter 作為第二個(gè)參數(shù):用來(lái)調(diào)用其他的getter
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
})
引入輔助函數(shù)mapGetters,方法和mapState一樣,講上面的mapState改成mapGetters就可以了
什么是嚴(yán)格模式:
在嚴(yán)格模式下,無(wú)論何時(shí)發(fā)生了狀態(tài)變更且不是由 mutation 函數(shù)引起的,將會(huì)拋出錯(cuò)誤。這能保證所有的狀態(tài)變更都能被調(diào)試工具跟蹤到。
開啟嚴(yán)格模式,僅需在創(chuàng)建 store 的時(shí)候傳入 strict: true:
const store = new Vuex.Store({
// ...
strict: true
})
什么是狀態(tài)變更管理
Vuex要求組件將狀態(tài)樹視為只讀,組件不應(yīng)該直接修改狀態(tài)樹上的狀態(tài), 而是通過提申請(qǐng)的方式,由狀態(tài)庫(kù)來(lái)實(shí)際執(zhí)行狀態(tài)變更的操作:

在嚴(yán)格模式下,Vuex的狀態(tài)約定為只讀的,因此我們只能將其單向映射 為組件的只讀計(jì)算屬性,更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交
mutation
const store = new Vuex.Store({
state:{number:0},
mutations:{
INCREASE(state,payload){ state.number= payload.num}
}
})
這里可以傳兩個(gè)參數(shù)一個(gè)是state,另一個(gè)是提交的時(shí)候傳過來(lái)的參數(shù),可以是個(gè)字符串,也可以是個(gè)對(duì)象,如果這里需要接收多個(gè)參數(shù),只能以對(duì)象的形式傳,mutations里面的函數(shù)沒有第三個(gè)參數(shù),提交代碼如下:
this.$store.commit('INCREASE', {
num: 10
});
//也可以這樣傳,type為函數(shù)名,其他的都是傳參
this.$store.commit({
type: 'INCREASE',
num: 10
})
這里可以使用 mapMutations 輔助函數(shù),和之前的state,getter差不多,代碼如下
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
//名字一樣時(shí)可以用數(shù)組的形式
...mapMutations([
'INCREASE'
// `mapMutations` 也支持載荷:
'INCREASE' // 將 `this.INCREASE(amount)` 映射為 `this.$store.commit('INCREASE', amount)`
]),
...mapMutations({
add: 'INCREASE' // 也可以設(shè)置成想要的函數(shù)名稱
})
}
}
然而mutation是同步的,不能寫異步代碼
為什么要保證狀態(tài)變更的同步性
Vuex作為一個(gè)狀態(tài)管理系統(tǒng),其核心特性就在于保證每一個(gè)狀態(tài)變更(mutation)的 可跟蹤性,異步代碼會(huì)導(dǎo)致狀態(tài)變更與應(yīng)用狀態(tài)的不一致,因而導(dǎo)致了應(yīng)用狀態(tài)的不可預(yù)測(cè)性。
我們?cè)赗ESET變更處理器中加入了異步代碼:
const store = new Vuex.Store({
state:{ number:0},
mutations:{
reset: state => setTimeout(() => state.number= 0, 3000)
}
})
當(dāng)事件觸發(fā)是狀態(tài)counter被重置為0,
但現(xiàn)在的問題是當(dāng)點(diǎn)擊按鈕的同時(shí)couter狀態(tài)并沒有馬上變化,而是3秒鐘后異步代碼執(zhí)行后才發(fā)生改變,這就導(dǎo)致不可預(yù)測(cè),這個(gè)時(shí)候就引入了action
如何使用action
const store = new Vuex.Store({
state:{number:0},
mutations:{
INCREASE(state,payload){ state.number= payload.num}
},
actions:{
//寫法一
add(context) {
context.commit('INCREASE')
}
//寫法二
add({ commit }) {
commit('INCREASE')
}
})
// 這里用到了對(duì)象的結(jié)構(gòu)
//因?yàn)楹瘮?shù)的參數(shù)是一個(gè)對(duì)象,函數(shù)中用的是對(duì)象中一個(gè)方法,我們可以通過對(duì)象的
//解構(gòu)賦值直接獲取到該方法
//因?yàn)閏ontext本身就是一個(gè)對(duì)象,里面有state對(duì)象和commit方法例如
let context {
state: {},
commit: function(){}
}
//根據(jù)對(duì)象結(jié)構(gòu)可以定義如下:
let {state,commit} = context
console.log(state)//state: {};
console.log(commit)//commit: function(){};
//所以放在函數(shù)里面就是
add({state,commit} ) {
commit('INCREASE')
}
調(diào)用this.$store.dispatch('add')
如何使用Module
由于將整個(gè)應(yīng)用的狀態(tài)保存在單一的狀態(tài)樹中,對(duì)于復(fù)雜的應(yīng)用而言, 這個(gè)狀態(tài)樹將相當(dāng)?shù)拇?。因此,Vuex允許我們將狀態(tài)樹拆分為狀態(tài)管理模塊(module)
例如,下面定義了兩個(gè)狀態(tài)模塊add和add1:
const add= {
state:{number:0},
mutations:{ INCREASE(state){state.number++} }
}
const add1 = {
state:{number1:0},
mutations:{ADD(state,val){state.time = val}}
}
const store = new Vuex.Store({
modules:{
a1:add,
a2: add1
}
})
訪問模塊的狀態(tài)
//訪問a1模塊的number1狀態(tài),
console.log(this.$store.state.a1.number1)
//訪問a2模塊的number2狀態(tài)。
console.log(this.$store.state.a2.number2)