其实对于软件开发模式来说,Angular 有着整套的一条龙服务,而 React 只是单纯的解决 View 层的问题,如果只是使用 React 开发项目会或多或少有点麻烦。下面主要讨论下数据层的东西,之前出了一个 mobx 来解决这个问题,但是这里想换个思路套用一下。其实 mobx 主要是声明了 @action, @computed, @observable 等元素来做到将 Store 作为一个可监控的源头,自动做到 VM 的效果,下面我也是,不过我采用 Rx 来做这个事情,简单利用下这种思想,能不能不污染我的原始数据(因为如果是双向的一种数据结构,那么就会被包装成监听类型的数据结构),这样我们调试的时候依然看到的是清晰的数据,并且还可以解决最初 Flux 库的一些麻烦,经过 Rx 改造的结果,可能比 mobx 的可测试性更好一些,具体就不说了,先谈 DEMO。
如果不想看文章的可以直接看代码 GitHub
这里有几个元素:
他们之间的依赖关系:
这样基本做到了视图和视图数据的干净依赖,通过 Service 的封装进行了解耦。在视图内部又是自更新的,所以对内的更新也是对外封闭的,只对注入的 Service 依赖的原始数据有关。
├── README.md
├── dist // 生成目录
│ └── app.js
├── index.html // 入口页面
├── package.json
├── src // 开发源码
│ ├── App.tsx // 应用入口
│ ├── components // 组件类
│ ├── containers // 容器类
│ ├── filters // 过滤器
│ ├── interface // 接口
│ ├── services // 服务类(单例)
│ ├── tsconfig.json // ts 的配置文件
│ └── utils // 工具类
├── webpack.config.js
└── yarn.lock
主要拆分的目录如上,这样如果一个系统的服务有很多可重用的情况下,就比较好抽离出来了,针对数据,如果后端是原始数据也需要一个数据管道的过滤层。
为什么要使用 TypeScript 呢? 因为 Rx 是数据流的一个操作过程,如果对过程中的数据类型是鸭子类型的话,就比较不好跟踪和判断了,所以我这里采用了 TypeScript,这样对数据也更灵敏一些。
配置其实没多少行,这里就不多介绍了,然后主要介绍下 containers
和 services
。这里我们的场景很简单,就是有 2 个按钮:添加
、删除
,数据就是不同的字符串,直接用 DOM 展示了出来。
containers/TokenList
// 1. 挂载后从服务层获取数据,并且订阅这个数据的更新
componentDidMount() {
// this.subject$ 是 Rx-Subject 的实例
this.subject$ = TokenListService.get();
this.subject$.subscribe((tokens: IToken[]) => {
this.setState({ tokens });
});
}
// 2. 对数据的操作都通过服务层
// 数据添加
TokenListService.put('lulin');
// 数据删除
TokenListService.del(id);
其实对于容器类来说,在订阅的时候已经定义好了界面的同步刷新,那么这个同步刷新数据的流入肯定就是在服务层去声明的,在后面服务层的代码中可以看出。
这里其实可以类比 Flux 来看,Flux 的流程是:
对比 Rx 的方式:
总体上来看,代码量估计是有减少的,流程也更短。
services/TokenList.service
// 生成私有的 tokens 视图数据
let tokens: Array<IToken> = [];
// 生成个流程作业的实例
let tokens$ = new Subject<IToken[]>();
// 基本上你要流入新数据只需要调用这个
tokens$.next(tokens);
// 这是保证触发,但是也可以不加
tokens$.complete();
整个服务层来讲,由于 Rx 的对外封装,提供简单接口的方式,这里也少了一些模板和多余的数据。
=..= 国外很多都玩过了吧,这里弄一个简单的例子来描述一下这种方式,Rx 是可以兼容到 IE8 的,mobx 不行,所以如果有需要是可以完美组合的,并且有测试需求的估计也比 mobx 好一些,大多数抽象得好,不需要测试视图。
扫码关注w3ctech微信公众号
共收到0条回复