前言
本文由前端早读课专栏作者
阿里数据技术与产品部前端团队诚身带来的分享。正文从这开始~
在react+redux已经成为大部分前端项目底层架构的今天,让我们再次回到软件工程界一个永恒问题的探讨上来,那就是如何提升一个开发团队的开发效率?
从宏观的角度来讲,其实只有良好的抽象才能真正提高一个团队的开发效率,而囿于不同产品所面临的不同业务需求,当我们抽丝剥茧般地将一个个前端工程抽象到最后一层,那么剩下的其实就只有按钮、输入框、日历、对话框、图标等这些毫无业务含义的UI组件了。
选择或开发一套适合自己团队使用的UI组件库应该是每一个前端团队在底层架构达成共识后下一件就要去做的事情,那么我们就以今天为始,分别从以下几个方面来一起探讨如何构建一套优秀的UI组件库。
第一个问题:选择开源vs自己造轮子
在React界,优秀且开源的UI组件库有很多,国外的如material-ui,国内的如ant-design,都是经过众多使用者检验,组件丰富且代码质量过硬的组件库。
所以当你决定自己再造一套UI组件库之前,不妨先尝试下这些在UI组件库界口碑良好的标品,再决定是否要亲自进入这个看似简单但实则困难重重的领域。
在这里,我们并不会去比较任何组件库之间的区别或优劣,但却可以从产品层面给出几个开发自有组件库的判断依据,仅供参考。
产品有独立的设计规范,包括但不限于组件样式、交互模式。
产品业务场景较为复杂,需要深度定制某些通用组件。
团队需要同时支撑多个相似产品。
设计思想:规范vs自由
在选择了自己造轮子这样一条路之后,下一个摆在面前的艰难的选择就是,要造一个规范的组件库还是一个自由的组件库?
规范的组件库可以从根本上保证产品视觉、交互风格的一致性,也可以很大程度上降低业务开发的复杂度,从而提升团队整体的开发效率。但在遇到一些看似相似实则不同的业务需求时,规范的组件库往往会走入一个可怕的死循环,那就是A需求需要使用A组件,但是现有的A组件不能完全支持A需求。这时摆在工程师面前的就只有两条路,从零开始把A需求开发一遍或者侵入A组件代码去支持A需求。方法一费时费力,会极大地增加本次项目的开发成本,方法二会导致A组件代码膨胀且逻辑复杂,极大地增加组件库后期的维护成本。
在多次陷入上面所描述的这个困境之后,最近一次内部组件库重构时,我们选择了拥抱自由,这其中既有业务方面的考虑,也有React在组件自由组合方面的天然优势,让我们来看一个例子。
这是一个非常传统的Select组件,触发Select的部分为Select的值及一个箭头,我们来看下面的一个业务场景:
这里的选择器不再是value加一个箭头,而是一个自定义元素,点击后展开下拉列表。虽然它的交互和Select一模一样,但这时候我们就不能再用当前的这个Select去实现它了。
在传统的value和箭头之外,更自由的Select添加了label及children支持,分别可以对应有名称的Select
或类似上面这种自定义的选择器。
同样的还有Select的孪生兄弟Dropdown。
这是一个常见的下拉列表的组件,是否允许用户传入ItemComponent其实就是一个规范与自由之间的博弈。而在选择了拥抱自由之后,组件的使用者终于不用再被组件所定义好的DOM结构所束缚,可以自由地组织自定义下拉元素。
是的,相较于传统的规范组件,自由的组件需要使用者在业务项目中多写一些代码,但如果我们往深处多看一层,这些特殊的下拉元素本就是属于某个业务所独有的,将其放在业务代码层恰恰是一种更合适的分层方法。
而另一方面,我们在这里所定义的自由,绝不仅仅是多暴露几个渲染函数那么简单,这里的自由,指的是组件DOM结构的自由,因为一旦某个组件定死了自己的DOM结构,外部除了重写样式去强行覆盖外没有任何其他可行的方式去改变它。
虽然我们上面提到了许多自由的好处,但很多时候我们还是会被一个问题所挑战,那就是自由的组件在大部分时候真的很难用,因为调用起来很麻烦。
这个问题其实是有解的,那就是默认值。我们可以在组件内部内置许多常用的组成元素,当用户不指定组成元素时,使用默认组成元素来渲染,这样就可以在规范与自由之间达到一个良好的平衡。当然,这里也有一个贴心小提示,那就是如果你真得希望在规范与自由之间达到一个良好的平衡,一定要提前做好组件库工作量增加三分之一的准备。
或者你也可以选择针对不同的使用场景,做两套不同的解决方案,例如前端开源UI框架界的翘楚antDesign,其底层依赖的react-