首先什么是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)確來說是要求應(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)庫:
Vuex的Store類 —— 狀態(tài)庫 —— 用于管理狀態(tài)樹,它的實(shí)例化配置項(xiàng)state 用來聲明要?jiǎng)?chuàng)建的狀態(tài)樹那伐,代碼如下:
const store = new Vuex.Store({
state:{ numner:0 }//state:存儲(chǔ)狀態(tài)踏施。也就是變量
})
如何使用狀態(tài)庫:
為了避免每個(gè)組件都要引入,我們可以在vue實(shí)例化的時(shí)候?qū)顟B(tài)庫掛接為Vue實(shí)例的一個(gè)屬性上
new Vue({
store:store, //使用store配置項(xiàng)罕邀,就可以將狀態(tài)庫掛接為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里面定義的字段和頁面要顯示的字段是一樣的話畅形,也可以寫成數(shù)組模式
...mapState([
'number ',
'number 1'
])
什么時(shí)候使用getter:
getter:官方的解釋是可復(fù)用的計(jì)算屬性 —— 派生狀態(tài),說明白了也就是對(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ù):用來調(diào)用其他的getter
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
})
引入輔助函數(shù)mapGetters,方法和mapState一樣,講上面的mapState改成mapGetters就可以了
什么是嚴(yán)格模式:
在嚴(yán)格模式下毕荐,無論何時(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)庫來實(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í)候傳過來的參數(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ù)拇蟆R虼耸嚎琕uex允許我們將狀態(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)