本文是對 Flux、Redux、Vuex、MobX 幾種經常使用狀態管理模式的總結,偏向於概念層面,不涉及過多代碼。javascript
狀態管理就是,把組件之間須要共享的狀態抽取出來,遵循特定的約定,統一來管理,讓狀態的變化能夠預測。html
組件之間一般會有一些共享的狀態,在 Vue 或者 React 中咱們通常會將這部分狀態提高至公共父組件的 props
中,由父組件來統一管理共享的狀態,狀態的改變也是由父組件執行並向下傳遞。這樣會致使兩個問題:vue
在應用調試過程當中,可能會有跟蹤狀態變化過程的需求,方便對某些應用場景的復現和回溯。這時候就須要統一對狀態進行管理,並遵循特定的約定去變動狀態,從而讓狀態的變化可預測。java
Store 模式是一種相對簡單的狀態管理模式,通常有如下約定:vuex
store
裏(也能夠是全局變量)store
中的 state
用於存儲數據,由 store
實例維護store
中的 actions
封裝了改變 state
的邏輯流程圖以下:redux
若是對 state 的變動均經過 actions,那麼實現記錄變動、保存快照、歷史回滾就會很簡單,可是 Store 模式並無對此進行強制約束。promise
Flux 是一種架構思想,相似於 MVC 、MVVM 等。數據結構
Flux 把一個應用分紅四部分:架構
Notice:app
type
屬性賦值一個大寫的字符串,代表是常量,加強可維護性,例如:{
type: 'ADD_USER',
payload: {
name: 'user_name'
}
}
複製代碼
state
以及用於觸發 state
更新的 dispatch
方法等,整個應用僅有單一的 Store。Store 中提供了幾個管理 state
的 API:
store.getState()
:獲取當前 statestore.dispatch(action)
:觸發 state
改變(惟一途徑)store.subscribe(listener)
:設置 state
變化的監聽函數(若把視圖更新函數做爲 listener 傳入,則可觸發視圖自動渲染)action.type
更新 state
並返回 nextState
替換原來的 state
的同步的純函數(對於相同的參數返回相同的返回結果,不修改參數,不依賴外部變量)。即經過應用狀態與 Action 推導出新的 state:(previousState, action) => newState
。Reducer 返回一個新的 state總體流程爲:Action Creator => action
=> store.dispatch(action)
=> reducer(state, action)
=> state = nextState
。流程圖以下:
Redux 還支持中間件,用於管理異步數據流。
Redux 的 Middleware 是對 store.dispatch()
進行了封裝以後的方法,可使 dispatch
傳遞 action 之外的函數或者 promise;經過 applyMiddleware
方法應用中間件。(middleware 鏈中的最後一個 middleware 開始 dispatch action 時,這個 action 必須是一個普通對象)
經常使用庫:redux-actions, redux-thunk, redux-promise 。
const store = createStore(
reducer,
// 依次執行
applyMiddleware(thunk, promise, logger)
)
複製代碼
store.dispatch(action)
),Store 調用 Reducer 計算出新的 state ,若 state 產生變化,則調用監聽函數從新渲染 View (store.subscribe(render)
)store.dispatch()
是 View 發出 Action 的惟一途徑Vuex 是 Vue 的狀態管理模式。
mapState
輔助函數將 state 做爲計算屬性訪問,或者將經過 Store 將 state 注入全局以後使用 this.$store.state
訪問store.commit()
調用 Mutationstore.dispatch()
方法觸發mapActions
輔助函數將 vue 組件的 methods 映射成 store.dispatch
調用(須要先在根節點注入 store)store.dispatch()
調用 Action ,在 Action 執行完異步操做以後經過 store.commit()
調用 Mutation 更新 State ,經過 vue 的響應式機制進行視圖更新MobX 背後的哲學是:
任何源自應用狀態的東西都應該自動地得到。
意思就是,當狀態改變時,全部應用到狀態的地方都會自動更新。
舉個栗子:
const obj = observable({
a: 1,
b: 2
})
autoRun(() => {
console.log(obj.a)
})
obj.b = 3 // 什麼都沒有發生
obj.a = 2 // observe 函數的回調觸發了,控制檯輸出:2
複製代碼
參考: