积梦前端采用的 React 状态管理方案: Rex
栏目: JavaScript · 发布时间: 5年前
内容简介:积梦(积梦的前端基于 React 做开发的. Rex 是我们在前端使用的状态管理方案, 类似 Redux.从名字也可以看, Rex 是一个基于 Redux 做了大幅简化的方案.
积梦( https://jimeng.io) 是一个为制造业制作的一个平台.
积梦的前端基于 React 做开发的. Rex 是我们在前端使用的状态管理方案, 类似 Redux.
从名字也可以看, Rex 是一个基于 Redux 做了大幅简化的方案.
另一方面, Rex 跟 Immer 有比较好的整合, 能够很轻松得使用不可变数据.
先前的技术方案
在开发 Rex 之前, 我们主要采用了 mobx-state-tree 的方案, 以及试验过 Redux.
最早的代码使用了 mobx 搭配 mobx-state-tree, 比较迎合 observe 的用法.
但是使用 mobx 全家桶遇到了一些比较困扰的问题,
- mobx 对数据封装的话,数据量比较大的时候初始化非常慢, 对应图表.
- observable 数据调试很不方便, 打印在 Console 是一个难以读取的对象.
- mobx-state-tree 内置了 types, 加上偶尔有改版, 经常出现不可控, 比如报错, 字段修改.
由于我一直就是 immutable 数据的支持者, 就一直在试验能否用不可变数据解决这些问题.
但是早先主要是 immutablejs 方案, 按照以前的使用经验, 成本比较高.
后来出现了 immer, 在工业聚当有 Micheal 的介绍下我们开始局部尝试, 取得了不错的效果.
而且因为 immer 也是 mobx 全家桶作者 Micheal 发布的模块, 使用也比较顺畅.
最初我尝试过用 immer 搭配 Redux 来局部替换一些全局状态,
试验之后我觉得效果上没有达到预期,
-
Redux 的 action/dispatch 在 JavaScript 当中没有足够灵活,
在函数式语言比如 Clojure 当中, 一切解释表达式, 默认不可变数据, 处理 action 非常顺畅,
但是用 JavaScript, 加上 immer 之后好一些, 但还是需要显式地到处引入 immer. -
TypeScript 类型跟 Redux 配合比较麻烦, 需要非常明确定义好各个 Action.
在 ReasonML 当中用代数类型很容易定义不同的 Action, 而 TypeScript 相对繁琐.
而且早先因为代码处理不干净, 类型推断并不是生效, 影响了实际体验.
所以 Redux 方案没有按预期地推进下去.
Rex 的特点
其实不管 Redux 还是 mobx-state-tree. 我想要的还是状态透传的功能.
通过 @connect(() => {})
来封装组件, 让局部能获得访问全局状态的能力.
至于具体的数据操作, immer 已经做到我们可以接受的程度了.
后来在知乎看到过别人模仿 Redux 开发的类库, 我萌生了自己裁剪 Redux 代码的想法.
在同事的帮助下优化了 decorator 部分的代码, 我大致梳理出这样一个类库,
@connect()
Rex 的使用
目前 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... .
以上所述就是小编给大家介绍的《积梦前端采用的 React 状态管理方案: Rex》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 【译】采用微前端架构
- JEECMS v9 发布,前端技术采用 VUE 框架
- 前端采用 Bootstrap 4 开发的 Xiuno BBS 4.0 正式版发布
- DevOps采用现状情况报告
- Swift 采用语言服务器协议
- jquery减少了Silverlight的采用?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
内容创业:内容、分发、赢利新模式
张贵泉、张洵瑒 / 电子工业出版社 / 2018-6 / 49
越来越多的内容平台、行业巨头、资本纷纷加入内容分发的战争中,竞争非常激烈。优质的原创性内容将成为行业中最宝贵的资源。在这样的行业形势下,如何把内容创业做好?如何提高自身竞争力?如何在这场战争中武装自己?是每一位内容创业者都应该认真考虑的问题。 《内容创业:内容、分发、赢利新模式》旨在帮助内容创业者解决这些问题,为想要进入内容行业的创业者出谋划策,手把手教大家如何更好地进行内容创业,获得更高的......一起来看看 《内容创业:内容、分发、赢利新模式》 这本书的介绍吧!