積夢(https://jimeng.io) 是一個爲製造業製做的一個平臺.
積夢的前端基於 React 作開發的. Rex 是咱們在前端使用的狀態管理方案, 相似 Redux.
從名字也能夠看, Rex 是一個基於 Redux 作了大幅簡化的方案.
另外一方面, Rex 跟 Immer 有比較好的整合, 可以很輕鬆得使用不可變數據.前端
在開發 Rex 以前, 咱們主要採用了 mobx-state-tree 的方案, 以及試驗過 Redux.
最先的代碼使用了 mobx 搭配 mobx-state-tree, 比較迎合 observe 的用法.
可是使用 mobx 全家桶遇到了一些比較困擾的問題,git
因爲我一直就是 immutable 數據的支持者, 就一直在試驗可否用不可變數據解決這些問題.
可是早先主要是 immutablejs 方案, 按照之前的使用經驗, 成本比較高.
後來出現了 immer, 在工業聚當有 Micheal 的介紹下咱們開始局部嘗試, 取得了不錯的效果.
並且由於 immer 也是 mobx 全家桶做者 Micheal 發佈的模塊, 使用也比較順暢.github
最初我嘗試過用 immer 搭配 Redux 來局部替換一些全局狀態,
試驗以後我以爲效果上沒有達到預期,npm
因此 Redux 方案沒有按預期地推動下去.bash
其實無論 Redux 仍是 mobx-state-tree. 我想要的仍是狀態透傳的功能.
經過 @connect(() => {})
來封裝組件, 讓局部能得到訪問全局狀態的能力.
至於具體的數據操做, immer 已經作到咱們能夠接受的程度了.異步
後來在知乎看到過別人模仿 Redux 開發的類庫, 我萌生了本身裁剪 Redux 代碼的想法.
在同事的幫助下優化了 decorator 部分的代碼, 我大體梳理出這樣一個類庫,ide
@connect()
的語法, 進行數據透傳,目前 Rex 通過半年多的使用驗證, 大體已經趨向穩定, 代碼在 GitHub 上能夠查看,
https://github.com/jimengio/rex
或者經過 npm 安裝到本地,函數
npm install @jimengio/rex
使用 Rex 首先就是要定義全局狀態的結構, 好比:工具
export interface IGlobalStore { obj: { a: number; }; b: string; } export let initialStore: IGlobalStore = { obj: { a: 2 }, b: "b" };
而後初始化一個 globalStore
, 包含該狀態:性能
import { createStore } from "@jimengio/rex"; export let globalStore = createStore<IGlobalStore>(initialStore);
這裏若是你想獲取 store 的狀態, 經過一個方法來讀取,
globalStore.getState()
以及監聽 store 的改變, 處理重繪:
globalStore.subscribe(() => { // rerender });
當你要對數據進行操做時, 有兩個方法可使用, update
和 updateAt
.
這兩個方法直接將 immer 封裝在內, 雖然是賦值操做, 但其實是不可變數據,
若是你對 immer 有疑問, 請仔細閱讀它的文檔並自行試驗 https://github.com/mweststrat...
其實 updateAt
是 update
的語法糖, 對於特定分支的數據的修改相對方便:
export function doIncData() { globalStore.update((store) => { store.b = "modified data"; }); globalStore.updateAt("obj", (obj) => { obj.a += 1; }); }
這個抽象大體從 Clojure 的 Atom 借鑑, 數據並不能直接修改.
若是你要修改狀態, 就須要發送一個函數給 Rex, 而後 Rex 會在內部進行修改.
此外也提供了 RexProvider
connectRex
useRexContext
等函數, 跟 Redux 習慣儘可能一致.
基於這些函數, 就能實現一個簡單的狀態管理, 以及數據更新的透傳.
Rex 實現較爲簡單, 目前沒有作更深層的優化, 也在避免引入新概念.
實際使用除了一些模板代碼, 主要是 immer 的不可變數據須要注意.
immer 使用的是可變數據的寫法, 可是內部經過 proxy 機制進行了轉化, 達到不可變數據的效果.
平時寫代碼的時候須要注意區分可變和不可變的數據, 比較寫法上是相似的.
另外要注意上面好比 doIncData
函數, 若是內部包含異步操做, 須要注意,
Rex 並不能支持異步, 因此在異步事件先後, 都須要直接調用 .update()
,
也就是說對應會有兩個(甚至多個)更新事件, 界面會更新屢次.
Rex 封裝時, 考慮到性能問題, 作了一些基本的 shouldComponentUpdate
檢測.
不過對於 useRexContext
這個 Hooks 的寫法. 目前沒有想明白怎麼樣處理, 須要手動處理.
其餘關於積夢前端的模塊和工具能夠查看咱們的 GitHub 主頁 https://github.com/jimengio .
招聘的計劃和條件也在 GitHub 上有給出 https://github.com/jimengio/h... .