用一個通俗易懂的概念來解釋狀態管理:全局變量。
但是在項目的開發中,我們應該都記得前輩的叮囑:儘量不要或少用全局變量,因為那是不可控的操作,任意的操作都可能導致數據的改變,造成全局污染,無法追蹤數據變化過程,所以開發中我們小菜鳥也大都避免去過多的操作全局變量。
但當項目複雜度比較高時,也許多個組件、多個頁面之間需要實現一種數據或狀態的共享,這時候,我們就可以將這些狀態統一的進行管理,既可以實現共享狀態,又能追蹤到數據的變化,可能這也是狀態管理誕生的一種原因吧。
當然,跟全局變量一樣,各個文章裡面也是叮而囑之,如果沒有哦必要,儘量不要使用狀態管理。
關於如何在UI試圖中合理地修改state,Facebook提出了flux思想。
Flux 是一種架構思想,專門解決軟體的結構問題。後來的rudux和vux也都是由Flux的思想演化出來的。
Flux將一個應用分成四個部分: View(視圖)、Action(動作)、Dispatcher(派發)、Store(數據)
這是一個單向流動的過程,
用戶訪問view -> 觸發事件action -> Dispatcher知道後告知store要更新 -> store更新,觸發視圖View更新頁面
redux的核心概念:
Redux store 是單一數據源,且store是 不可變 的, Redux 沒有 dispatcher 的概念 ,
Store 中提供了幾個管理 state 的 API:
Action Creator -> 觸發action -> store.dispatch(action) -> reducer(state, action) -> 更新state
MobX 是通過透明的函數響應式編程使得狀態管理變得簡單和可擴展,是一個用法簡單優雅、同時具有可擴展性的狀態管理庫。
和 Redux 對單向數據流的嚴格規範不同,Mobx 只專注於從 store 到 view 的過程。在 Redux 中,數據的變更需要監聽,而 Mobx 的數據依賴是基於運行時的,這點和 Vuex 更為接近。
如果大家使用過 Vue 的話相信對其雙向綁定 MVVM 的思想並不陌生,React + Mobx 相當於是 Vue 全局作用域下的雙向綁定,而 Vue 的狀態管理框架 Vuex 卻是借鑑了 Flux 架構,連尤大都說,似乎有點你中有我,我中有你的關係。
仍然放一張vuex的示意圖:
vuex的運作原理跟redux稍有不同。因為Vue雖然是單向數據流,但Vue 基於 ES5 中的 getter/setter 來實現視圖和數據的 雙向綁定 ,因此 Vuex 中 state 的變更可以通過 setter 通知到視圖中對應的指令來實現視圖更新。且state不是通過actions來修改的,而是通過mutations。
用戶訪問view -> 觸發事件action ->action中觸發對應的mutation -> 在mutation函數中改變state -> 通過 getter/setter 實現的雙向綁定的機制,視圖View會自動更新頁面
使用一句話總結: commit mutation,dispatch action
從上面幾種熱門的狀態管理實現方式來看,可以發現,這幾種數據流模型幾乎都是從 action 到 view 之間的一種數據流動,總的過程可以大致簡化為:
1、 數據狀態中心: state和store
可以發現,在redux和flux中,數據狀態用store表示,而在vuex和mobx中,這個store被state替代。
和 Redux 中使用不可變數據來表示 state 不同, Vuex 中沒有 reducer 來生成全新的 state 來替換舊的 state,Vuex 中的 state 是可以被修改的 。
Vuex 中的 state 是可修改的,而修改 state 的方式不是通過 actions,而是通過 mutations。更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。
2、 行為action
我們想要更新視圖內容,第一步就是要有觸發的動作,action就是向store發起更新請求的最小單元。但action並非是一個動詞,它是一個行為的描述,本質上是 一個純聲明式的數據結構,僅提供對事件的描述,不提供事件的具體邏輯
在rudux中,生成action有兩種方式:
3、dispatch
在各類應用狀態管理的模型中,通常都會有一個 dispatch 方法,它就聲明在 Store 上,負責調用各個 Action ,然後由 Store 上對應的分發機制進行處理。
4、Reducer / Mutation
現在到了我們的第三步,更新狀態。flux和mobx對狀態更新的處理是直接更改,而redux和vuex中間還會多出一個reducer和mutation來處理更新的工作。
至於reducer和mutation,分別是針對redux和vuex的不同工作機制。
先看reducer, Actions 只能描述發生了什麼,並不能描述狀態發生了什麼變化, Reducers 指定 state tree 將要發生什麼,它主要的工作內容是:接受一個action,然後通過switch匹配action的type,作出相應的處理後,返回一個 新的對象 。為什麼是新的對象呢?因為redux最核心的一個概念,store是 不可變 的, Redux 是一個實踐 函數式編程(FP) 理念的庫 。下面是一個最簡單的reducer:
const items = (state = [], action) => { switch (action.type) { case "ADD_ITEM": return [...state, { text: action.text }] default: return state }}
再來看mutation,一個 mutation 是由一個 type 和與其對應的 handler 構成的,type 是一個字符串類型用以作為 key 去識別具體的某個 mutation,handler 則是對 state 實際進行變更的函數。
// storeconst store = { books: []}// mutationsconst mutations = { [ADD_BOOKS](state, book) { state.books.push(book) }}