vuex
vuex是狀態(tài)管理模式驶鹉。
需求:比如在我們的博客中,每個組件中都需要用戶的登錄狀態(tài)以及登錄信息(多個視圖依賴于同一狀態(tài)室埋,來自多個視圖的行為需要變更同一狀態(tài)),這個時候词顾,就可以使用vuex來維護這個狀態(tài)。
vuex的核心就是倉庫store肉盹,其實就是一個容器,包含應用中的很多狀態(tài)(state)上忍,以及管理狀態(tài)的方法。vuex的狀態(tài)存儲是響應式的窍蓝。
const store = new Vuex.Store({
state: {
isLogin: false
},
getters:{},
mutations:{},
actions:{}
})
下面介紹核心概念
一腋颠、State
state翻譯為狀態(tài),就是需要維護的狀態(tài)吓笙,在上邊例子已經展示。
問題:如何獲得vuex狀態(tài)面睛?
我們上邊已經說了,vuex的狀態(tài)存儲是響應式的叁鉴。
vue文檔中,data中幌墓,有這么一句話:大概來說,data 應該只能是數(shù)據(jù) - 不推薦觀察擁有狀態(tài)行為的對象常侣。
那么,如何獲取呢袭祟?我們么可以通過計算屬性返回某個狀態(tài)。
計算屬性巾乳,是用來處理邏輯運算的
// 創(chuàng)建一個 Counter 組件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.isLogin
}
}
}
那么,如果我們有很多組件胆绊,這樣,太煩了压状!
vuex提供了store選項,將狀態(tài)從根組件注入到每個子組件中种冬。然后我們在子組件中,就可以通過this.$store
訪問娱两。(如何訪問,當然還是通過computed屬性訪問)
const app = new Vue({
el: '#app',
store
})
感覺這倆沒啥區(qū)別十兢?
區(qū)別挺大的:要是我們的組件比較多趣竣,注入之后旱物,就不要在組件中一個一個導入了。
輔助函數(shù)mapState
用處:當一個組件需要獲取多個狀態(tài)的時候宵呛,如果我們將每一個都聲明為計算屬性,真的會很煩宝穗,輔助函數(shù)可以幫我們簡化這個過程讽营。
比如橱鹏,在我們的博客中莉兰,要維護的狀態(tài)有用戶的登錄狀態(tài)以及用戶的登錄信息:
const store = new Vuex.Store({
state: {
isLogin: false,
user: {}
}
})
輔助函數(shù)的用法:
// 在單獨構建的版本中輔助函數(shù)為 Vuex.mapState
import { mapState } from 'vuex'
//當映射的計算屬性名稱和state中狀態(tài)名稱相同時杉辙,這么用
//就是this.isLogin = store.state.isLogin
computed: mapState([
'isLogin',
'user'
])
//簡化上邊的寫法蜘矢,使用對象展開符
computed: {
...mapState({
'isLogin','user'
})
}
二岖食、Getter
getter就像store的計算屬性一樣泡垃。
比如我們在state維護了一個數(shù)組,我們將state的數(shù)據(jù)做一些處理惧浴,再使用赶舆。按照我們剛才說的芜茵,當任何一個組件需要使用處理后的數(shù)據(jù)時九串,都需要把這個過程再重復一次猪钮,顯然是不劃算的肘交。
如果我們能在store中將數(shù)據(jù)處理好涯呻,再暴露出來,豈不是更好效诅。
這就是getter的用途乱投。
在我們的博客項目中褐荷,為什么也使用getter呢层宫?
我們的狀態(tài)很簡單,只有isLogin/user限匣,用來存儲用戶的登錄狀態(tài)以及信息贮庞。但是麻煩的是物喷,我們分了模塊。
store
---modules
------auth.js
------blog.js
---index.js
這樣依賴尉辑,每次實際上都是看到的狀態(tài)state->auth->isLogin/user隧魄,這樣的結構麻煩堤器,不方便訪問闸溃,所以才將其放到getter中,getter和state是同級的乓旗。直接用就可以
const getters = { isLogin: state=>state.isLogin, user: state=>state.user }
就像上邊的例子一樣汇跨,Getter接受state作為其第一個參數(shù)穷遂。
問題:如何訪問getter
- 通過屬性訪問
- 通過方法訪問
mapGetters輔助函數(shù):用法和剛才的都一樣
三、Mutation
其實忌穿,這個問題應該在最開始就提:
state我們用來定義狀態(tài)掠剑。要是我想要改這些狀態(tài)呢?
比如糕珊,用戶需要注銷登錄澜公、頁面跳轉到另一個人的時候,我們需要將用戶信息更改掉蝶防。這些需求殷费,我們就需要通過mutation來完成仍律。
Mutation是干啥的水泉?
文檔中說:更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。
mutation示例:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 變更狀態(tài)
state.count++
}
}
})
如果想調用mutation娶靡,就需要用:
store.commit('increment')
問題:如果我們在修改狀態(tài)的時候塔鳍,需要傳入數(shù)據(jù)呢呻此。
這就是payload(載荷)。其實就是向store.commit
傳入額外的參數(shù)就行了糯彬。
store.commit('increment', payload)
Mutation必須是同步函數(shù)
在組件中當然也是可以提交mutation的
this.$store.commit('xxx')
或者使用輔助函數(shù)也是可以
我沒用,需要時搓谆,再看文檔把
四、Action
既然mutation必須是同步的斩萌,那么我們就用action處理異步就可以了术裸。
需要注意:
- Action提交的是mutation袭艺,不可直接變更狀態(tài)
我們的博客項目中答倡,我們要維護用戶的登錄狀態(tài)以及信息。
用戶登錄前后的信息获茬,我們肯定是需要維護的佩谣,但是登錄实蓬、注冊之類的要搞成異步啊调鬓。那么這些就只能在Action中定義了,當在Action中異步登錄成功燕锥,就可以開開心心提交mutation修改登錄狀態(tài)了。
Action的用法:(博客登錄異步處理暇榴,當然auth.login肯定封裝好的)
const actions = {
login({ commit }, { username, password }) {
return auth.login({ username, password })
.then(
res => {
commit('setUser', { user: res.data })
commit('setLogin', { isLogin: true })
})
}
}
或者看文檔的例子,可能更直接一點彬犯。
問題:既然Action都是異步的,那啥時候結束呢宋列?(結束之后仇参,才好去提交mutation罢┢埂)
使用promise就行了...上邊例子怕磨,auth.login
就是返回的promise對象肠鲫,接著then就行了...
async/await當然也可以...就是我沒太用過
問題:搞了這么久导饲,Action如何在組件中使用啊袋毙?
使用mapActions在組件的method中映射下听盖,直接this.xxx
用就行了