关于组件库设计的文章一搜能出来一大把,但大多数都是从UI角度或者视觉规范层面来说的,但随着前端技术的发展和迭代,前端这个岗位早已不是过去定义的实现样式那么简单了,这篇文章会站在一个技术同窗的角度来聊一下组件库的设计除了样式还有哪些能够关注的。javascript
组件的本质其实在于代码的复用和抽象,以此起到提高开发效率的目的, 能够说一个组件的灵魂就在于对业务场景的解构,好比各类控件的抽象,事件的抽象,样式的抽象等,并经过组合和配置的方式实现业务需求,某种程度上一个组件库就像是一个工具箱,为业务场景的开发提供各类零件,而要如何设计这些零件,就须要对应用场景有一个深刻的了解和思考。前端
好比C端的组件库,须要在UI,性能,浏览器兼容性上有更多的思考,追求更极致的交互体验和视觉体验,同时C端应用的UI常常会根据节日,活动的主题而切换, 在组件库的设计上也要考虑到个性化的扩展空间。java
而B端的组件库,则更加注重易用性和可复用性,保证中台或者B端工具类应用的高速迭代和高效使用。同时B端应用会涉及不少的数据展现,和增删改查操做,这就须要组件库在交互控件上有更细的职责划分和更丰富的选择。react
除了应用的业务场景不一样,还可能存在平台场景的多元化问题,好比同一套组件库是否能在H5和小程序中复用。这些都须要组件库设计者在规划之初就考虑进去。webpack
一类是基于几大前端框架的生态来实现的,在设计上都已经造成了本身的风格和规范,也有本身的沉淀,好比基于Vue生态的element, 基于react的antD 等。他们的优势是已经发展的很成熟了基本上能够cover大多数的业务场景,缺点是组件库在跨框架迁移上的成本较大。web
还有一类是组件库则是针对跨端的需求设计的。一般底层会依赖一套跨平台开发的框架 如京东的taro,美团的mpVue, 淘宝的Rax等,他们的核心思想也是 write one run anywhere, 这类组件库在实现上, 主要利用框架提供的基础实现尽量抹平各个平台的差别,让使用者能够基于一套开发规范,实现多个平台的业务。这类组件的优势是,能够减小开发者在跨平台上的学习成本,缺点是组件库的丰富度还有所欠缺,能覆盖的场景也比较局限canvas
除了上述的两大类,腾讯的omi,则是利用web comp的特性,来实现的跨端和跨框架,能够算是下一代前端框架的一个尝试了。小程序
组件库的设计过程其实也很相似一款产品的设计过程,会有前期的场景调研,竞品分析, 需求整理,用户体验(这里应该叫开发体验),以及持续的试错迭代。浏览器
综合上面的一些思考和分析,我会试着把组件库规划以下:前端框架
组件需求:
组件胶水层 --> 实现组件和实际的业务之间的衔接
组件代理层 --> 能够基于代理实现组件内部的灵活调用和局部刷新
组件交互层 --> 根据业务场景 抽象基于交互事件的功能,并经过装饰器注入
组件扩展层 --> 实现组件间的克隆,继承,扩展
组件库cli --> 方便组件的迭代和工程化
性能 --> 实现最小粒度的从新渲染
组件库解决痛点
组件内部系统:
样式
事件
状态
继承
组件库架构选型(暂定,后期可能还会调整)
以rax为基础,结合mono repo, peer dep 和 组件的多态协议 开发, 实现按需引入,保证业务调用层在跨端场景下的接口统一,最大发挥各个端的特性。
组件库features(暂定,后期可能还会调整):
Modal.proxy.visible = true; Modal.show(config) 复制代码
扩展继承
//克隆 const Modal2 = Modal.clone(); 复制代码
//扩展 const Modal2 = genModal({ methods: { cancel() { console.log('%c rewrite the cancel','color:#299865',this); this.visible = false; } } }); 复制代码
//批量扩展 import {factoryAuto} from 'component' const {Button, Modal} = factoryAuto(pubConfig); 复制代码
//继承 const Button2 = genButton(Button1.proxy, newFeature) 复制代码
轻量的状态组件
<Button
x-for={(item, key) in statusList}
type="+success"
onClick={_ => trySingle(item)} >
wait{key}
</Button>
复制代码
function trySingle (item) { performance.watch() item.choosed = !item.choosed if (item.choosed) { return new Status('pending...', { backgroundColor: 'green' }) } else { return new Status(null) } } 复制代码
@addTransition('visible') class BaseMix extends Base {} 复制代码
<Button scope={item}
x-for={(item, key) in scopeList}
type="+success"
onClick={_ => {tryScope(item)}} >
wait{key}
</Button>
复制代码
function tryScope(item) { performance.watch(); item.choosed = !item.choosed; } 复制代码
@addLoading class EventCtxMix extends EventCtxBase {} 复制代码
function Okfunc() { return new Promise((resolve, reject) => { //封装了防重锁和loading效果 setTimeout(() => { resolve() }, 1600) }) } 复制代码
前端技术的一个特色就是变化快,除了各大框架提供的组件能力, 这几年web components 的概念也逐渐成为热点。除此以外随着react hooks的横空出世 function components时代也随之而来,相比于class compontents 基于hooks的function compontents在设计上更加灵活但外部扩展性也相对较差,基于这层考虑我有一个常识性的构想是在框架上层封装组件的逻辑层和样式层的接口,经过胶水层和组件链接只借助组件完成视图层的渲染,从而打破组件库和框架的次元壁,组件库的核心部分能够迁移到其余框架甚至web compontents,只须要从新coding胶水层就好了。固然这个构想距离最终落地还须要大量的实践基础。