@medux 數據流

歡迎您開始 @medux 之旅,建議您依次閱讀如下 4 篇文章,這將耗費您大約 30 分鐘。javascript

第 4 篇:medux 數據流vue

-- Github 地址 ---java

@medux 數據流示意圖

data-flow.png

基於 Redux

由於 Medux 基於 Redux,因此部分數據流與 Redux 很類似,好比:react

  • 保持全局單例的 Store
  • Store 和 View 之間使用單向數據流
  • 改變 Store 數據,必須經過 Reducer
  • 調用 Reducer 必須經過顯式的 dispatch Action

模塊化 Store

  • 每一個 module 僅能經過 reducer 修改 Store 下的某個一級子節點(moduleState),跨 module 不能直接修改
  • 每一個 module 能夠讀取全部 Store 的子節點
  • Store 一級子節點除了 moduleState 還能夠是其它 ReduxReducers 管理的節點(好比 route),它們依然遵循以上原則

封裝 Effect

  • 將全部反作用封裝在 Effect 中執行
  • Effect 要修改 Store,必須從新 dispatch Action 經過 Reducer 來執行
  • Effect 能夠經過 dispatch Action 來觸執行另外一個 Effect
  • Effect 執行是異步的,可使用 await 來跟蹤其執行結果,好比:
...
await this.dispatch(this.action.searchList());
this.dispatch(this.action.showPop());
複製代碼

跟蹤 Effect 的執行

你只需在定義 Effect 的裝飾器中加入可控的參數既可注入其 loading 狀態到 moduleState 中:git

// loadingForGroupName 注入加載狀態的分組key,默認爲global,若是爲null表示不注入加載狀態
// loadingForModuleName 可將loading狀態合併注入到其餘module,默認爲入口主模塊
function effect(loadingForGroupName?: string | null, loadingForModuleName?: string)

// 例如
@effect('global')
public async login(username:string, password:string){
  ...
}
複製代碼

除了 loading 狀態,你還能夠直接編寫 effect 執行先後的鉤子:github

function logger(before: (action: Action, moduleName: string, promiseResult: Promise<any>) => void, after: null | ((status: 'Rejected' | 'Resolved', beforeResult: any, effectResult: any) => void));
複製代碼

讓 Action 具備 Event 性質

reducer 或 effect 咱們統稱爲 ActionHandler,當執行 store.dispatch(action)時,會觸發一個目標 ActionHandler 的執行,咱們稱之爲主ActionHandler。除了主 ActionHandler,還能夠存在一系列從ActionHandler來配合執行,它們能夠屬於不一樣的 module,因此一般用來解決 module 之間的協做。web

從本文頂部的 medux 數據流示意圖中看出,藍色的 Action 彷佛像一條總線穿透各個 module,它的 Event 性質讓整個模塊變得鬆散起來typescript

ActionHandler 的執行順序

一個 Action 被 dispatch 可能引發一系列 reducer 和 effect 執行,那麼它們的執行順序是怎樣的呢?redux

  • 主ActionHandler老是先執行
  • 從ActionHandler默認是按註冊順序,可是你能夠設置 Action.priority 來強制干預
  • reducer 是同步的,它們老是先執行
  • effect 是異步的,它們會併發執行,除非你使用 await
interface Action {
  type: string;
  priority?: string[]; //執行優先級
  payload?: any[];
}
複製代碼

當 ActionHandler 執行出錯時

當 actionHandler 執行出錯時,medux 會自動 dispatch 一個 type 爲medux.Error的新 Action,你能夠 handler 這個 ErrorAction,並對錯誤進行處理:api

  • 若是在處理中繼續 throw 錯誤,將再也不重複 dispatch ErrorAction,當前代碼將中斷執行
  • 不然被視爲解決了錯誤,代碼繼續往下執行

View 和 Component

View 本質上就是一個 Component,可是 View 用來展現業務,Component 用來展現交互。從本文最開始的 Medux 數據流示意圖中看出:

  • View 一般訂閱了 Store,並從 Store 中之間得到數據。Component 則只能經過 props 來進行傳遞
  • View 必定屬於某個 Module。Component 能夠屬於某個 Module 專用,也能夠屬於所有 Module
  • View 和 Component 之間能夠相互嵌套
  • View 和 View 之間也能夠相互嵌套,可是不能直接經過 import 另外一個 view,必須經過 loadView 方法加載
const RoleSelector = loadView('adminRole', 'Selector');
複製代碼

關於 RouteState

框架會自動監聽路由的變化,並將路由信息解析爲 RouteState,而後:

  • 經過dispatch medux.RouteChangeAction 將其注入 Redux 一級子節點 route 中
  • 經過dispatch moduleName.RouteParamsAction 將其注入相應的 moduleState
  • 你能夠監聽以上 2 個 action 來作一些事情

使用 MutableData 可變數據

喜歡 vue 或 mobx 的朋友可能會問,medux 是要求可變數據仍是不可變數據?

雖然 medux 是基於 redux 的,但本着實用至上的原則,並不要求嚴格遵循 redux 模型,它是另外一個 flux 框架。

medux 框架內部會使用 ImmutableData 來自動生成並管理 state 及其 1 級節點,對於這個內置數據結構一般你也無需干預。而對於次級的 moduleState 你能夠將它定義爲 一個 MutableData,而後直接在 reducer 中修改 state 並返回它,儘管這有違 reducer 的本意,但這是對接 MutableData 最簡單靈活的方案。

CoreAPI

查看 CoreAPI 文檔

web+medux+react

@medux/react-web-router:整合封裝了@medux/core、@medux/web、@medux/route-plan-a、@medux/react, 是 web 環境下開發 react 的開箱即用框架

Demo

medux-react-admin:基於@medux/react-web-router和最新的ANTD 4.x開發的通用後臺管理系統,除了演示 medux 怎麼使用,它還創造了很多獨特的理念

相關文章
相關標籤/搜索