随着前端的快速发展,从原来的简单交互到jQuery, 从 Kissy, YUIAngular, React, Vue等等。 我也曾想,这些技术的发展,什么是真正的发展?什么只是外表的改变? 关于真正的发展的这个问题,我的答案是:从原始的农耕 -> 到模块化 -> 再到组件化。组件化无疑是最近最大的进步与发展。 这篇文章,很大程度是 code-review理想中的组件化的延伸。

  • 组件化
  • 组件化愿景
  • 为什么是子集
  • 子集不够用怎么办
  • 要闹哪样
  • 数据绑定
  • 数据流的管理
  • 技术之外

组件化

拿我熟悉的 Vue 说吧,Vue 的几大特点:

  • 组件化
  • 模板语法
  • 数据流的管理及组件间通讯
  • 双向绑定
  • Virtual Dom 好,就做那个比较简单,大家也比较熟悉的实验。将他们几个特性写在纸上,然后,一个一个划去,直到剩下最后一个。 (当然,境界要是够高的话,可以做到心中无胜过外在有,开个小玩笑)。

在我看来划去的步骤是:模板语法 -> 数据流管理 -> 双向绑定 -> Virtual Dom,剩下一个组件化留到最后。

组件化愿景

我之前也一直在探索 WebComponents 在实际项目中的应用,曾尝试过私有的组件化标准, 之后又找到了类似的(主要是和我的私有组件化比较类似)、较为成熟的(相比我自己的组件化而言)解决方案: riot, 之后也尝试过 Polymer 方案,再之后,由于 Weex 的使用,不得不上 Vue 组件化。但对 WebComponents 念念不忘。

前几天,和阿里巴巴 赵振宇 老师简单交流了一下,我问了他前端框架的未来选型的这个问题,刚好他再近期也在解决这个问题,他给出了他的解决方案:

在 Vue,React 框架之外,再抽象一层DSL,设计一套基于 WebComponents 子集的技术规范,并在此基础之上,加上足够多的代码约束来满足业务的需要。
(只是原话的大概意思 )

听到他的这种想法之后,我感觉豁然开朗,思维打开了好多。我当初有好多的疑问,也问了赵老师。以下是基于他的想法加我理解的笔记(未必是赵振宇老师真实想法,仅供参考)。

为什么是子集

为什么是 WebComponents 的子集,而非它的超集?

这个,我先插另外一件事,两年前,我向 张鑫旭 老师请教了我关于想增强 alert 方法的想法。下面是他的回复。 tim 20170807103516

alert 的处理我以前也折腾过,后来放弃了,JS的原始API最好不好动的好,也不要在 DOM 原型上扩展事件。

这话结合为什么是子集这个问题?我有了更深的体会。就像之前,我自己在 Date.prototype 去扩展 format 对象一样,但我看到有人评价这种方式很 stupid 的时候,我有点奇怪,郁闷,现在我又明白了些。

子集不够用怎么办

答案是语法约束。

WebComponentsTemplate 不够用怎么办?循环用 Vue 的 v-for,还是 mustache 的 , 还是 Polymer 的 dom-repeat

我的理解是(当然赵振宇老师也有提到过),模板语法无约束,你可以随心所欲用你的模板,jade, handlerbar whatever,但是转换后的 AST ( Abstract Syntax Tree, 抽象语法树) 需要统一。这颗 AST 是创建前端的核心。而这颗 AST 就是所谓的语法约束了,这可能对整个框架和架构的设计者提出了较大的挑战,但对于写业务代码的同学,可能会更灵活。

之后,构建好这颗 AST 后,怎么创建 View 呢?哈,这个就相对比较简单了,你想用 Vue 的解决思路的话,你可以去生成 Vue 可以 render 的函数就行了,你不想用 Vue , 但想用 Virtual Dom ? 也行啊,你可以按照某个 Virtual Dom 的规范去生成对应的 Grnerator, 比如: Matt-Esch/virtual-dom。什么?你连 Virtual Dom 都不想用?也行啊!创建 Real Dom,用 morphdom 优化一下也是个不错的选项。

要闹哪样?

之前跟老师谈看源码的问题,说我看了 Vue 源码,也抽取了 双向绑定, virtual-dom 等模块,谈到分模块细粒度的问题。确实,双向绑定从 Vue 中单独抽取出来没有多大的意义,必须和框架结合在一起才能发挥它的价值,像virtual-dom这种粒度的提取可能更有意义,也更有价值,当然,也正因为如此,在 Github 上,virtual-dom的单独库可能有更多的人愿意去尝试。

老师问了我抽取模块粒度的问题,之后我也问了老师同样的问题。

模板独立抽象之后,如果想双向绑定又该如何实现,数据流的绑定又怎么处理会比较恰当呢?

数据绑定

既然已经独立于框架之外了,那数据绑定该怎么办?老师提供了两种数据绑定方案:

  • 页面层级的统一配置管理
  • 代码编译期间的预编译处理,将需要绑定的数据在编译期间做特殊的约束处理

优劣简要分析:

  • 页面层级的配置,可能会更直观,但配置的管理可能会随着项目的增大而变得困难
  • 而编译期间的处理,会有更好的封装性,但在运行时的灵活性会有所降低

这块处理会有点麻烦,因为独立于框架之外,又只能是子集,所以,只能说约束,而这个约束的标准,需要兼顾各个前面提到的模板,很考验设计者的宏观统筹能力,该舍的要舍,该留的要留。谁舍谁留,保证满足业务需求的前提下,最好找到各个模板的共同子集,最小化子集。在此之上,各个模板可以有自己的编译期间能力,但运行时能力必须相同。当然,最好,还能让写代码的写得舒服。

数据流的管理

数据流的管理,之前,在我看来,任何框架,包括 ReactVue,可能只需要用 Redux 这套标准就够了。但如果要抽离出来,在框架之外抽象,Redux 可能也会有所限制。怎么办?

老师给出的方案是:通过外部数据流管理器,来管理组件间的数据流。在用 Redux 前后,数据流大概是这样的,这里我借用一下知乎上dbody作者画的两幅图:

tim 20170807113020 tim 20170807113027

但,按老师的思路,数据流可能是这样的:

tim 20170807114626

通过一个数据流管理器,将数据流从一个组件到另一个组件,上一个组件的输出就是下一组件的输入。这种模式,跟消息的订阅发布模式很很大不同,是简单的 Pipe 模式,这种的限制和订阅发布比起来,很大的不足当然是,数据流只能一个一个流下去,也没那么直观?如果把这两种模式结合在一起呢?

tim 20170807115443

这样,有和 Redux 没多大区别了,这块,不是很能理解。有待进一步发掘。

技术之外

技术为业务服务,技术为应用而生。前端技术的快速发展固然是好事,但对于大企业来说,框架的快速变更,可能未必是好事。相反,在企业内部,需要有技术沉淀,业务沉淀。不能因为框架的火爆而选择,需要理性对待。那如何让技术人员聚焦在业务代码就成了大难题。所以,赵振宇老师目前正在攻克的就是这个难题。我也比较感兴趣,也觉得比较有意义。

当然,我依然有自己的疑惑。如何将这种脱离框架型架构,通用化后回馈给开源社区呢?如何给开源社区贡献自己的一份力量?