Redux 是 JavaScript 狀態容器,提供可預測化的狀態管理。react
在 Redux 中,最爲核心的概念就是 action 、reducer、store 以及 state,那麼具體是什麼呢?編程
嚴格的單向數據流是 Redux 架構的設計核心。json
Redux 應用中數據的生命週期遵循下面 4 個步驟:redux
核心庫:數組
1 |
react |
目錄結構:promise
1 |
├─app |
不過使用過 Redux 的人會有這些痛點:難懂的 API、複雜的邏輯、過多的代碼侵入。Redux 採用單一根節點、函數式編程、動做分離管理(彷佛讓項目很容易管理),這些都是 Redux 過於複雜的緣由。然這裏並非說 Redux 很差。基於項目自己,尋找一個最適合的框架纔是優的解決方案。網絡
MobX 是一個通過戰火洗禮的庫,它經過透明的函數響應式編程(transparently applying functional reactive programming - TFRP)使得狀態管理變得簡單和可擴展。數據結構
比起Redux,Mobx基於觀察者模式,採用多節點管理數據,是一個很輕量、入手簡單、代碼耦合小的數據框架。react-router
MobX 爲單向數據流,也就是動做改變狀態,而狀態的改變會更新全部受影響的視圖。架構
它由幾個部分組成:Actions、State、Computed Values、Reactions。使用 MobX 將一個應用變成響應式的可概括爲如下步驟:
MobX 爲現有的數據結構(如對象,數組和類實例)添加了可觀察的功能。 經過使用 @observable
裝飾器來給你的類屬性添加註解就能夠簡單地完成這一切。這樣改屬性就變成了「被觀察者」。
1 |
class Store { |
observer
函數裝飾器能夠用來將 React 組件轉變成響應式組件。 它用 mobx.autorun
包裝了組件的 render
函數以確保任何組件渲染中使用的數據變化時均可以強制刷新組件。 observer
是由單獨的 mobx-react
包提供的。
1 |
@observer |
這樣 Index 組件就變成了一個響應式的組件(智能組件),當「被觀察者」改變時,該組件就會自動更新。
React 組件一般在新的堆棧上渲染,這使得一般很難弄清楚是什麼致使組件的從新渲染。 當使用 mobx-react 時能夠定義一個新的生命週期鉤子函數 componentWillReact
。當組件由於它觀察的數據發生了改變,它會安排從新渲染,這個時候 componentWillReact
會被觸發。這使得它很容易追溯渲染並找到致使渲染的操做(action)。
inject
函數裝飾器能夠將 Store 數據注入到組件當中。inject
是由單獨的 mobx-react
包提供的。
1 |
@inject("store") |
使用 MobX,能夠定義在相關數據發生變化時自動更新的值。 經過 @computed
裝飾器調用 的getter / setter 函數來進行使用。
1 |
class ItemsStore { |
當添加了一個新的 items 時,MobX 會確保 total 自動更新。
action 是任一一段能夠改變狀態的代碼。具體實現代碼以下:
1 |
class HomeStore { |
若是是在嚴格模式:
1 |
import { useStrict } from 'mobx'; |
那麼 MobX 會強制只有在動做之中才能夠修改狀態。對於任何不使用動做的狀態修改,MobX 都會拋出異常。
action 包裝/裝飾器只會影響當前運行的函數,而不會影響當前函數調度(但不是調用)的函數! 這意味着若是你有一個 setTimeout、promise 的 then 或 async 語句,而且在回調函數中某些狀態改變了,這些回調函數也應該包裝在 action 中。可使用 action 關鍵字來包裝 promises 回調函數
1 |
@action |
異步 action 實現的方式還有多種,這裏只列舉了 action 關鍵子的模式
在 React 中使用 MobX 須要用到 mobx-react。
其提供了 Provider 組件用來包裹最外層組件節點,而且傳入 store 傳遞給後代組件:
1 |
import React from 'react'; |
使用 @inject
給組件注入其須要的 store(利用 React context 機制);
經過 @observer
將 React 組件轉化成響應式組件,它用 mobx.autorun 包裝了組件的 render 函數以確保任何組件渲染中使用的數據變化時均可以強制刷新組件:
1 |
import React, {Component} from 'react' |
其中 @withRouter
是 router 的 參數傳入到組件中。