狀態管理之 Flux、Redux、Vuex、MobX(概念篇)

本文是對 Flux、Redux、Vuex、MobX 幾種經常使用狀態管理模式的總結,偏向於概念層面,不涉及過多代碼。javascript

狀態管理

什麼是狀態管理?

狀態管理就是,把組件之間須要共享的狀態抽取出來,遵循特定的約定,統一來管理,讓狀態的變化能夠預測html

爲何須要狀態管理?

狀態共享

組件之間一般會有一些共享的狀態,在 Vue 或者 React 中咱們通常會將這部分狀態提高至公共父組件的 props 中,由父組件來統一管理共享的狀態,狀態的改變也是由父組件執行並向下傳遞。這樣會致使兩個問題:vue

  • 須要將共享的狀態提高至公共的父組件,若無公共的父組件,每每須要自行構造
  • 狀態由父組件自上而下逐層傳遞,若組件層級過多,數據傳遞會變得很冗雜

變化跟蹤

在應用調試過程當中,可能會有跟蹤狀態變化過程的需求,方便對某些應用場景的復現和回溯。這時候就須要統一對狀態進行管理,並遵循特定的約定去變動狀態,從而讓狀態的變化可預測。java

Store 模式

Store 模式是一種相對簡單的狀態管理模式,通常有如下約定:vuex

  • 狀態存儲在外部變量 store 裏(也能夠是全局變量)
  • store 中的 state 用於存儲數據,由 store 實例維護
  • store 中的 actions 封裝了改變 state 的邏輯

流程圖以下:redux

若是對 state 的變動均經過 actions,那麼實現記錄變動、保存快照、歷史回滾就會很簡單,可是 Store 模式並無對此進行強制約束。promise

Flux

Flux 是一種架構思想,相似於 MVC 、MVVM 等。數據結構

Flux 的組成

Flux 把一個應用分紅四部分:架構

  • View:視圖層
  • Action:動做,即數據改變的消息對象(可經過事件觸發、測試用例觸發等)
    • Store 的改變只能經過 Action
    • 具體 Action 的處理邏輯通常放在 Store 裏
    • Action 對象包含 type (類型)與 payload (傳遞參數)
  • Dispatcher:派發器,接收 Actions ,發給全部的 Store
  • Store:數據層,存放應用狀態與更新狀態的方法,一旦發生變更,就提醒 Views 更新頁面

Notice:app

  • Action 本質上是一個純聲明式的數據結構,僅提供對事件的描述,不提供事件的具體邏輯。一般會給 Action 的 type 屬性賦值一個大寫的字符串,代表是常量,加強可維護性,例如:
{
  type: 'ADD_USER',
  payload: {
    name: 'user_name'                              
  }
}
複製代碼

Flux 的特色

  • 單向數據流。視圖事件或者外部測試用例發出 Action ,經由 Dispatcher 派發給 Store ,Store 會觸發相應的方法更新數據、更新視圖
  • Store 能夠有多個
  • Store 不只存放數據,還封裝了處理數據的方法

Redux

Redux 的組成

  • Store:存儲應用的狀態 -- state 以及用於觸發 state 更新的 dispatch 方法等,整個應用僅有單一的 Store。Store 中提供了幾個管理 state 的 API:
    • store.getState():獲取當前 state
    • store.dispatch(action):觸發 state 改變(惟一途徑)
    • store.subscribe(listener):設置 state 變化的監聽函數(若把視圖更新函數做爲 listener 傳入,則可觸發視圖自動渲染)
  • Action:同 Flux ,Action 是用於更新 state 的消息對象,由 View 發出
    • 有專門生成 Action 的 Action Creator,其本質上是一個返回 Action 對象的函數
  • Reducer:是一個根據 action.type 更新 state 並返回 nextState 替換原來的 state同步的純函數(對於相同的參數返回相同的返回結果,不修改參數,不依賴外部變量)。即經過應用狀態與 Action 推導出新的 state:(previousState, action) => newStateReducer 返回一個新的 state

總體流程爲:Action Creator => action => store.dispatch(action) => reducer(state, action) => state = nextState。流程圖以下:

Middleware

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)
)
複製代碼

Redux 的特色

  • 單向數據流。View 發出 Action (store.dispatch(action)),Store 調用 Reducer 計算出新的 state ,若 state 產生變化,則調用監聽函數從新渲染 View (store.subscribe(render)
  • 單一數據源,只有一個 Store
  • state 是隻讀的,每次狀態更新以後只能返回一個新的 state
  • 沒有 Dispatcher ,而是在 Store 中集成了 dispatch 方法,store.dispatch() 是 View 發出 Action 的惟一途徑
  • 支持使用中間件(Middleware)管理異步數據流

Vuex

Vuex 是 Vue 的狀態管理模式。

Vuex 的核心概念

  • Store:Vuex 採用單一狀態樹,每一個應用僅有一個 Store 實例,在該實例下包含了 state, actions, mutations, getters, modules
  • State:Vuex 爲單一數據源
    • 能夠經過 mapState 輔助函數將 state 做爲計算屬性訪問,或者將經過 Store 將 state 注入全局以後使用 this.$store.state 訪問
    • State 更新視圖是經過 vue 的雙向綁定機制實現的
  • Getter:Getter 的做用與 filters 有一些類似,能夠將 State 進行過濾後輸出
  • MutationMutaion 是 vuex 中改變 State 的惟一途徑(嚴格模式下),而且只能是同步操做。Vuex 中經過 store.commit() 調用 Mutation
  • Action:一些對 State 的異步操做能夠放在 Action 中,並經過在 Action 提交 Mutaion 變動狀態
    • Action 經過 store.dispatch() 方法觸發
    • 能夠經過 mapActions 輔助函數將 vue 組件的 methods 映射成 store.dispatch 調用(須要先在根節點注入 store)
  • Module:當 Store 對象過於龐大時,可根據具體的業務需求分爲多個 Module ,每一個 Module 都具備本身的 state 、mutation 、action 、getter

Vuex 的特色:

  • 單向數據流。View 經過 store.dispatch() 調用 Action ,在 Action 執行完異步操做以後經過 store.commit() 調用 Mutation 更新 State ,經過 vue 的響應式機制進行視圖更新
  • 單一數據源,和 Redux 同樣全局只有一個 Store 實例
  • 只能應用於 Vue

MobX

MobX 背後的哲學是:

任何源自應用狀態的東西都應該自動地得到。

意思就是,當狀態改變時,全部應用到狀態的地方都會自動更新

MobX 的核心概念

  • State:驅動應用的數據
  • Computed values:計算值。若是你想建立一個基於當前狀態的值時,請使用 computed
  • Reactions:反應,當狀態改變時自動發生
  • Actions:動做,用於改變 State
  • 依賴收集(autoRun):MobX 中的數據以來基於觀察者模式,經過 autoRun 方法添加觀察者

舉個栗子:

const obj = observable({
  a: 1,
  b: 2
})

autoRun(() => {
  console.log(obj.a)
})

obj.b = 3 // 什麼都沒有發生
obj.a = 2 // observe 函數的回調觸發了,控制檯輸出:2
複製代碼

MobX 的特色

  • 數據流流動不天然,只有用到的數據纔會引起綁定,局部精確更新(細粒度控制)
  • 沒有時間回溯能力,由於數據只有一份引用
  • 基於面向對象
  • 每每是多個 Store
  • 代碼侵入性小
  • 簡單可擴展
  • 大型項目使用 MobX 會使得代碼難以維護

總結

  • Flux 、Redux 、Vuex 均爲單向數據流
  • Redux 和 Vuex 是基於 Flux 的,Redux 較爲泛用,Vuex 只能用於 vue
  • Flux 與 MobX 能夠有多個 Store ,Redux 、Vuex 全局僅有一個 Store(單狀態樹
  • Redux 、Vuex 適用於大型項目的狀態管理,MobX 在大型項目中應用會使代碼可維護性變差
  • Redux 中引入了中間件,主要解決異步帶來的反作用,可經過約定完成許多複雜工做
  • MobX 是狀態管理庫中代碼侵入性最小的之一,具備細粒度控制、簡單可擴展等優點,可是沒有時間回溯能力,通常適合應用於中小型項目中

參考:

相關文章
相關標籤/搜索