当前期刊数: 5
本周精读文章:单页应用的数据流方案探索
1 引言
前几期精读了前端模块化、语法相关的文章,这次讨论另一个举足轻重的话题:数据流。
数据流在前端的地位与工程化、可视化、组件化是一样重要的,没有好的数据流框架与思想的指导,业务代码长期肯定倾向于不可维护的状态,当项目不断增加功能后,管理数据变得更加重要。
早期前端是没有数据流概念的,因为前端非常薄,每个页面只要展示请求数据,不需要数据流管理。
随着前端越来越复杂,框架越来越内聚,数据流方案由分到合,由合又到了分,如今数据流逐渐从框架中解绑,形成了一套通用体系,供各个框架使用。
虽然数据流框架很多,但基本上可以分为 双向数据流党
、单向数据流党
、响应式数据流党
,分别以 Mobx
、Redux
、Rxjs
为代表呈现三国鼎立之状,顺带一提,对 css
而言也有 css in js
和纯 css党
势均力敌,前端真是不让人省心啊。这次我们来看看民工叔徐飞在 QConf 分享的主题:单页应用的数据流方案探索。
2 内容概要
文中主要介绍了响应式编程理念,提到的观点,主要有:
Reactive
数据封装- 数据源,数据变更的归一
- 局部与全局状态的归一
- 分形思想
- action 分散执行
- app 级别数据处理,推荐前端
Orm
整体来看,核心思路是推荐组件内部完成数据流的处理,不用关心使用了 Redux
Mobx
或者 Rxjs
,也不用关心这些库是否有全局管理的野心,如果全局管理那就挂载到全局,但组件内部还是局部管理。
最后谈到了 Rxjs
、xstream
响应式数据流的优势,但并未放出框架,仅仅指点了思想,让一些读者心里痒痒。但现在太多”技术大牛“把”业界会议“当成了打广告,或者工作汇报的机会,所谓授人以鱼不如授人以渔,这篇文章卓尔不群。
3 精读
一切技术都要看业务场景,民工叔的 单页应用数据流方案 解决的是重前端的复杂业务场景,虽然现在前端几乎全部单页化,但单页也不能代表业务数据流是复杂的,比如偏数据展示型的中台单页应用就不适合使用这套方案。
此文讨论的是纯数据流方案,与 Dom
结合的方案可以参考 cyclejs,但这个库主要搭建了 Reactive
-> Dom
的桥梁,使用起来还要参考此文的思路。
3.1 响应式数据流是最好的方案吗?
我认为前端数据流方案迭代至今,并不存在比如:面向对象 -> 函数式 -> 响应式,这种进化链路,不同业务场景下都有各自优势。
面向对象
以 Mobx 为代表,轻前端用的较多,因为复杂度集中在后端,前端做好数据展示即可,那么直接拥抱 js 这种基于对象的语言,结合原生 Map
Proxy
Reflect
将副作用进行到底,开发速度快得飞起。
数据存储方式按照视图形态来,因为视图之间几乎毫无关联,而且特别是数据产品,后端数据量巨大,把数据处理过程搬到前端是不可能的(为了推导出一个视图形态数据,需要动辄几 GB 的原始数据运算,存储和性能都不适合在前端做)。
函数式
以 Haskell 为代表,金融行业用的比较多,可能原因是金融对数据正确性非常敏感,不仅函数式适合分布式计算,更重要的是无副作用让数据计算更安全可靠。
个人认为最重要的原因是,金融行业本来很少有副作用,像前端天天与 Dom
打交道的,副作用完全逃不了。
响应式
以 Rxjs 为代表,重前端更适合使用。对于 React native
等 App 级别的开发,考虑到数据一致性(比如修改昵称后回退到文章详情,需同步作者修改后的昵称),优先考虑原始类型存储,更适合抽象出前端 Orm
作为数据源。
其实 Orm
作为数据源,面向对象也很适合,但响应式编程的高层次抽象,使其对数据源、数据变动的依赖可插拔,中等规模使用大对象作为数据源,App 级别使用 Orm
作为数据源,因地制宜。
3.2 分形思想
分形思想即充血组件的升级版,特点是同时支持贫血组件的被外部控制能力。
分形的优点
分形保证了两点:
- 组件和数据流融为整体,与外部数据流隔离,甚至将数据处理也融合在数据管道中,便于调试。
- 便于组件复用,因为数据流作为组件的一部分。
如果结合文中的 本地状态 概念,局部数据也放在全局,就出现了第三点好处:
- 创建局部数据等于创建了全局数据,这样代码调试可局部,可整体,更加灵活。
本地状态 可以参考 dva 框架的设计,如果没有全局 Redux
就创建一个,否则就挂载到全局 Redux
上。
分形的缺点
对于聊天室或者在线 IDE 等,全局数据居多,很多交叉绑定的情况,就不适合分形思想,反而纯 Redux 思想更合适。
3.3 数据形态,是原始数据还是视图数据?
我认为这也是分业务场景,文章提到不应该太偏向视图结构数据,是有道理的,意思是说,在适合原始结构数据时,就不要倾向于视图结构数据了。但有必要补充一下,在后端做了大量工作的中台场景,前端数据层非常薄,同时拿到的数据也是后端服务集群计算后的离线数据,显然原始数据结构不可能放在前端,这时候就不要使用原始数据存储了。
3.4 从原始数据到视图数据的处理过程放在哪
文中推荐放在 View
中处理,因为考虑到不想增加额外的 Store
,但不知道这个 Store
是否包含组件局部的 Store
。业务组件推荐使用内部数据流操作,但最终还是会将视图数据存在全局 Store
中,只是对组件而言,是局部的,对项目而言是全局的,而且这样对特定的情况,比如其他组件复用数据变更的监听可以支持到。
总结
我们到头来还是没有提供一个完美的解决方案,但提供了一个完整的思路,即在不同场景下,如何选择最合适的数据流方案。
最后,不要盲目选型,就像上面提到的,这套方案对复杂场景非常棒,但也许你的业务完全不适合。不要纠结于文中为何没有给出系统化解决方案的 Coding 库,我们需要了解响应式数据流的优势,同时要看清自己的业务场景,打造一套合适的数据流方案。
最后的最后,如有不错的数据流方案,解决了特定场景的痛点,欢迎留言。
如果你想参与讨论,请点击这里,每周都有新的主题,每周五发布。