React状态管理大乱斗,横向对比Dva,Rematch,Mirror
這年頭,Redux 狀態(tài)管理框架滿天飛,前幾天在網(wǎng)上閑逛偶然又發(fā)現(xiàn) Rematch、Mirror、Smox、Xredux,都用了一下,發(fā)現(xiàn)都是套瓷娃娃,大同小異,拿幾個(gè)比較歷害的來說:
- DvaJS Github Stars 12000+
- Rematch Github Stars 5000+
- Mirror Github Stars 1200+
無非就是類似這樣的:
model({state: ...,reducers: {aaa(playload)bbb(playload)},effects: {ccc(playload)ddd(playload)} }) 復(fù)制代碼審美疲勞了?H 起來,給大家推薦一款小鮮肉React-coat:
項(xiàng)目地址:github.com/wooline/rea…
class ModuleHandlers extends BaseModuleHandlers {@reducerpublic aaa(playload): State {...}@reducerprivate bbb(playload): State {...}@effect("ajaxLoading")public async ccc(playload) {...}@effect("loginLoading")private async ddd(playload) {...} } 復(fù)制代碼spring 風(fēng)格?ng 風(fēng)格?
可能你會(huì)說,用 Class 呀,不喜歡,我喜歡 FP 風(fēng)格。我想說,這是狀態(tài)管理框架非 React UI 框架,不要為了流行 FP 就皆 FP,就象當(dāng)年 JS 流行面向?qū)ο缶幊?#xff0c;把面向過程說成洪水猛獸。
武裝到牙齒的 TS 類型反射
React-coat 全面擁抱 Typescript,直接上圖:
action 調(diào)用時(shí)的類型反射:
動(dòng)態(tài)加載模塊時(shí)的類型反射:
Store State 結(jié)構(gòu)的類型反射:
連路由參數(shù)也有類型反射:
支持單頁 SPA 和服務(wù)器渲染 SSR 同構(gòu)
- 而且SSR 在開發(fā)時(shí)也可以享受:“熱更新”
- 還支持 SPA(單頁) + SSR(服務(wù)器渲染)一鍵切換。
打開項(xiàng)目根下的./package.json,在"devServer"項(xiàng)中,將 ssr 設(shè)為 true 將啟用服務(wù)器渲染,設(shè)為 false 僅使用瀏覽器渲染
關(guān)于服務(wù)器渲染SSR請(qǐng)移步另一篇文章:juejin.im/post/5c7f6e…
強(qiáng)大而便捷的 Dispatch Action
對(duì)比一下各大框架 Dispatch Action 的語法:
// Dva中 yield put({type: 'moduleA/increment', payload: 2});// Rematch中 dispatch.moduleA.increment(2);// Mirror中 actions.moduleA.increment(2);// React-coat中 import moduleA from "modules/moduleA/facade"; ... await this.dispatch(moduleA.actions.increment(2)); 復(fù)制代碼-
語法簡(jiǎn)潔性上,Dva 用的 saga 中的 yield put,還要寫 type 和 payload,最繁瑣。其它三款都直接用方法調(diào)用,更簡(jiǎn)潔。
-
Rematch 和 Mirror 等于把所有 action 都放到一個(gè)全局變量中去了,而 React-coat 去中心化,按需引入 moduleA,更利于系統(tǒng)保持松散結(jié)構(gòu)。
-
從語義上來說 React-coat 依然顯示的保留 dispatch 關(guān)鍵字,moduleA.actions.increment(2) 返回的是依然是 Action,dispatch(action) 作為 Redux 的基本理念得到完整的保持,Rematch 和 Mirror 已經(jīng)變成傳統(tǒng)的 MVC 了。
-
從功能上,只有 Dva 和 React 支持同步 effect。其它兩款都不支持,或者是我沒發(fā)現(xiàn)?什么是同步 effect?例如:
- query 會(huì)觸發(fā)一個(gè) effect,updateState 會(huì)觸發(fā)一個(gè) reducer
- updateState 需要等待 query 執(zhí)行完后再 dispatch
-
React-coat 的獨(dú)有的殺手锏:action 名稱和參數(shù)的類型反射和智能提示、public private 權(quán)限的控制,讓你感受什么才叫真正的封裝。試想下如果多人同時(shí)并行開發(fā)多個(gè)模塊,你還需要為你的模塊寫一大篇 API 說明文檔么?
徹底的模塊化
既然是企業(yè)級(jí)應(yīng)用,那模塊化自然是少不了的,包括模塊封裝、代碼分割、按需加載。模塊化的目的主要是拆分復(fù)雜系統(tǒng)、解耦與重用。
以上框架中,Rematch 和 Mirror 的模塊化功能比較弱,且不優(yōu)雅,略過。Dva 和 React-coat 都有強(qiáng)大的模塊化功能,其中 Dva 可以搭配 UMI 來自動(dòng)配置。
在 dva 中動(dòng)態(tài)加載 model 和 component,要靠路由配置:
{path: '/user',models: () => [import(/* webpackChunkName: 'userModel' */'./pages/users/model.js')],component: () => import(/* webpackChunkName: 'userPage' */'./pages/users/page.js'), } 復(fù)制代碼React-coat 中代碼分割和路由分層而治:
- 代碼分割只做代碼分割,不參和路由的事,因?yàn)槟K也不一定是非得用路由的方式來加載。
- 路由只做路由的事情,不參和代碼分割的事,因?yàn)槟K也不一定非得做代碼分割。
- 一個(gè) Module 整體打包成一個(gè) bundle,包括 model 和 views,不至于太碎片。
React-coat 中支持路由動(dòng)態(tài)加載,也支持非路由動(dòng)態(tài)加載
// 使用路由加載: const PhotosView = loadView(moduleGetter, ModuleNames.photos, "Main"); ... <Route exact={false} path="/photos" component={PhotosView} /> 復(fù)制代碼// 直接加載: const PhotosView = loadView(moduleGetter, ModuleNames.photos, "Main"); ... render() {const {showDetails} = this.props;return showDetails ? <DetailsView /> : <ListView />; } 復(fù)制代碼- Dva 以 Page UI 主線來劃分模塊;React-coat 以業(yè)務(wù)功能高內(nèi)聚、低偶合來劃分模塊。后者更適合解耦與重用。
- Dva 使用集中配置、將 Page、路由、model、代碼分割全部都集中寫在一個(gè)中心文件中;React-coat 去中心化,將各自的邏輯封裝在各自模塊中,并且 model、代碼分割、路由分層而治,互不干涉。后者更干凈整潔。
- Dva 將每個(gè) model 和 component 都做成一個(gè)代碼分割包;React-coat 將一個(gè) Module 整體做成一個(gè)代碼分割包,前者太碎,后者更符合 bundle 概念。
- React-coat 支持路由動(dòng)態(tài)加載 View,也支持非路由動(dòng)態(tài)加載 View,二條腿走路步子邁得更大。
- React-coat 動(dòng)態(tài)加載 View 時(shí)會(huì)自動(dòng)導(dǎo)入 Model,無需手工配置加載 Model,是真正的路由組件化。
更多差異還是請(qǐng)看:與 DvaJS 風(fēng)云對(duì)話,是 DvaJS 挑戰(zhàn)者?還是又一輪子?
跨模塊的調(diào)用與協(xié)作
在復(fù)雜的長業(yè)務(wù)流程中,跨模塊調(diào)用與協(xié)作是少不了的,Dva、Rematch、Mirror、React-coat 都支持跨模塊派發(fā) action,跨模塊讀取 State。比如:
// Mirror中 if(resphonse.success){actions.moduleA.doSomeEffect();actions.moduleB.doSomeEffect(); } 復(fù)制代碼這是一種串聯(lián)調(diào)用的模式,適應(yīng)于一些耦合緊密的業(yè)務(wù)流。 但對(duì)于一些松散耦合的業(yè)務(wù)流程,最佳的方式應(yīng)當(dāng)是觀察者模式,或叫事件廣播模式。
場(chǎng)景:當(dāng) moduleA 執(zhí)行了一個(gè) action,moduleB、moduleC、moduleD...都需要執(zhí)行一些各自的動(dòng)作
這就是 React-coat 獨(dú)有的殺手锏:ActionHandler 概念。
class ModuleB {//在ModuleB中監(jiān)聽"ModuleA/update" actionasync ["ModuleA/update"] (){await this.dispatch(this.action.featchData())} }class ModuleC {//在ModuleC中監(jiān)聽"ModuleA/update" actionasync ["ModuleA/update"] (){await this.dispatch(this.action.featchData())} } 復(fù)制代碼React-coat 主動(dòng)調(diào)用、事件廣播兩種模式都支持,二手都要抓,二手都要硬。就問你騷氣不騷氣??
總結(jié)
以上是生活随笔為你收集整理的React状态管理大乱斗,横向对比Dva,Rematch,Mirror的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 提审马甲包被拒问题记录
- 下一篇: 趣头条将获得阿里1.71亿美元的可转债,