Vuex
?是一個專為?Vue.js
?應用程序開發的狀態管理模式;集中存儲和管理應用的所有組件狀態。
-
狀態:什么是狀態,我們可以通俗的理解為數據。Vue只關心視圖層,那么視圖的狀態如何來確定?我們知道是通過數據驅動,這里的狀態管理可以簡單理解為管理數據。
-
集中存儲:
Vue
只關心視圖,那么我們需要一個倉庫(Store
)來存儲數據,而且是所有的數據集中存儲,視圖和數據就可以分析。 -
管理:除了存儲,還可以管理數據,也就是計算、處理數據。
-
所有組件狀態:所用的組件共用一個倉庫(
Store
),也就是一個項目只有一個數據源(區分模塊modules
)。 -
總結:Vuex就是在一個項目中,提供唯一的管理數據源的倉庫。
Vuex
將組件公用數據抽離,在一個公共倉庫管理,使得各個組件容易獲取(getter
)數據,也容易設置數據(setter
)。
Store
倉庫里面放了很多對象。其中state
就是數據源存放地,對應于與一般Vue
對象里面的data
(后面講到的actions
和mutations
對應于methods
)。
-
在使用
Vuex
的時候通常會創建Store
實例new Vuex.store({state,getters,mutations,actions})
有很多子模塊的時候還會使用到modules
。 -
-
總結,
Store
類就是存儲數據和管理數據方法的倉庫,實現方式是將數據和方法以對象形式傳入其實例中。要注意一個應用或是項目中只能存在一個Store
實例!!
state
里面存放的數據是響應式的,Vue
組件從store
中讀取數據,若是store
中的數據發生改變,依賴這個數據的組件也會發生更新。(這里“狀態”=“數據”),也就是是說數據和視圖是同步的。-
獲取:在
Vue
組件中獲取數據,最直接的可以通過計算屬性中獲取; -
組件仍然可以保存局部狀態:雖然說
Vuex
的Store
倉庫讓我們同一管理數據變得更加方便,但是代碼一多也會變得冗長,有些組件的數據是自己嚴格自用,我們可以將state
放在組件自身,作為局部數據,專供此組件使用,其他的組件不能用。
-
mapState
的作用是把全局的?state
?和?getters
?映射到當前組件的?computed
?計算屬性中,this.$store.state
。 -
使用示例
import {mapState} from 'vuex' export default {computer :mapState({count: state => state.count,'count' // 映射 this.count 為 store.state.count})
}
Store
倉庫里,state
就是用來存放數據,若是對數據進行處理輸出,比如數據要過濾,一般我們可以寫到computed
中。但是如果很多組件都getters
存在的意義。-
定義:我們可以在
store
中定義getters
,第一個參數是stateconst getters = {style:state?=>?state.style}
-
傳參:定義的
Getters
會暴露為store.getters
對象,也可以接受其他的getters
作為第二個參數; -
使用:
computed: { doneTodosCount () {return this.$store.getters.doneTodosCount}
mapGetters
輔助函數僅僅是將store
中的getters
映射到局部計算屬性中,用法和mapState
類似
import?{ mapGetters }?from?'vuex'
computed: {// 使用對象展開運算符將 getters 混入 computed 對象中...mapGetters(['doneTodosCount','anotherGetter',])}//給getter屬性換名字mapGetters({// 映射 this.doneCount 為 store.getters.doneTodosCountdoneCount: 'doneTodosCount'
})
Mutations
-
getters
是為了初步獲取和簡單處理state
里面的數據(這里的簡單處理不能改變
?state
里面的數據),Vue
的視圖是由數據驅動的,也就是說state
里面的數據是動態變化的,那么怎么改變呢,切記在Vuex
中store
數據改變的唯一方法就是mutation
! -
通俗的理解
mutations
,里面裝著一些改變數據方法的集合,這是Veux
設計很重要的一點,就是把處理數據邏輯方法全部放在mutations
里面,使得數據和視圖分離。
-
mutation結構:每一個
mutation
都有一個字符串類型的事件類型(type
)和回調函數(handler
),也可以理解為{type:handler()}
,這和訂閱發布有點類似。先注冊事件,當觸發響應類型的時候調用handker()
,調用type
的時候需要用到store.commit
方法。const store = new Vuex.Store({state: {count: 1},mutations: {increment (state) { //注冊事件,type:increment,handler第一個參數是state;// 變更狀態state.count++}}})store.commit('increment') //調用type,觸發handler(state)
-
載荷(payload):簡單的理解就是往
handler(stage)
中傳參handler(stage,pryload)
;一般是個對象。mutations: {increment (state, n) {state.count += n}}store.commit('increment', 10)
-
mutation-types:將常量放在單獨的文件中,方便協作開發。
// mutation-types.jsexport const SOME_MUTATION = 'SOME_MUTATION'// store.js import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types'const store = new Vuex.Store({state: { ... },mutations: {// 我們可以使用 ES2015 風格的計算屬性命名功能來使用一個常量作為函數名[SOME_MUTATION] (state) {// mutate state} } })
-
commit:提交可以在組件中使用?
this.$store.commit('xxx')
?提交?mutation
,或者使用?mapMutations
?輔助函數將組件中的?methods
?映射為?store.commit
?調用(需要在根節點注入?store
)。import { mapMutations } from 'vuex'export default {methods: {...mapMutations(['increment' // 映射 this.increment() 為 this.$store.commit('increment')]),...mapMutations({add: 'increment' // 映射 this.add() 為 this.$store.commit('increment')})}}
Actions
-
背景:在
mutation
中我們講到,mutation
中是存放處理數據的方法的集合,我們使用的時候需要commit
。但是commit
是同步函數,而且只能是同步執行。那我們想一步操作怎么辦? -
作用:在
actions
中提交mutation
,并且可以包含任何的異步操作。actions
可以理解為通過將mutations
里面處里數據的方法變成可異步的處理數據的方法,簡單的說就是異步操作數據(但是還是通過mutation
來操作,因為只有它能操作)
actions:
-
定義
actions
const store = new Vuex.Store({//創建store實例state: {count: 0},mutations: { increment (state) {state.count++}},actions: { //只是提交`commit`了`mutations`里面的方法。increment (context) {context.commit('increment')}}})一般我們會簡寫成這樣actions: {increment ({ commit }) {commit('increment')}}
-
分發
actions
store.dispatch('increment')
-
MapActions和MapState一級MapMutations類似。
Modules
-
背景:在
Vue
中State
使用是單一狀態樹結構,應該的所有的狀態都放在state
里面,如果項目比較復雜,那state
是一個很大的對象,store
對象也將對變得非常大,難于管理。 -
module
:可以讓每一個模塊擁有自己的state
、mutation
、action
、getters
,使得結構非常清晰,方便管理。
-
一般結構
const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... }} const moduleB = { state: { ... }, mutations: { ... }, actions: { ... }}const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB})
-
模塊內部的數據:①內部
state
,模塊內部的state
是局部的,也就是模塊私有的,比如是car.js
模塊state
中的list
數據,我們要通過this.$store.state.car.list
獲取;②內部getter
、mutation
和action
,仍然注冊在全局命名空間內,這是為了多模塊可以同時響應同一mutation
;this.$store.state.car.carGetter
的結果是undefined
,而通過this.$store.state.carGetter
則可以拿到。 -
傳參:
getters
====({state
(局部狀態),getters
(全局getters
對象),roosState
(根狀態)});actions
====({state
(局部狀態),commit
,roosState
(根狀態)}).