如何设计一个优秀的组件
阅读更多系列文章请访问我的GitHub 博客,本文示例代码请访问这里。
前言
在开发过程中,我们经常会遇到现有组件库无法满足需求,需要自己设计和实现组件的情况。那么,如何才能设计一个既满足产品需求,又易于开发人员使用的组件呢?本文就以一个级联组件的设计为例,探讨一下如何设计一个优质组件。
开始前准备
如果你想查看本文的 Demo 演示,请点击这里。
如果想查看源代码,请点击这里。
组件是用 React 实现的,如果你对它不了解,可以点击React 官网。
本文涉及到的源代码都由 TypeScript 编写,如果你对 TypeScript 不了解,可以查看TypeScript 官网
本文 Demo 中的级联组件,是基于Ant Design开发的,如果你对它不了解,可以先查看[组件总览](https://ant.design/components/overview-cn/)。
接下来我将详细叙述一下组件的设计与实现过程。
组件设计
需求分析
开发这个组件的原因是来自工作中遇到的一个需求。
产品提出的业务需求是实现一个地区的级联选择,并且应设计师要求,不能使用 Ant Design 的Cascader 级联选择,因此需要自己实现一个级联选择。
通常需要从 4 个角度对需求进行分析:
业务需求角度
UI 设计角度
开发人员角度
与其他组件配合角度
业务需求角度
在拿到一个需求之后,我们不应当直接考虑如何实现,而要先思考一下,这个需求是不是真正的需求。或者说,这个需求背后,是否还有更加基础和核心的需求。
现在,我们拿到了一个地区级联选择的需求,那么我们应该仅仅实现地区级联选择吗?我认为不是的,今天我们拿到的是地区选择的需求,明天就可能变成职业选择。
因此,我们实际需要实现的,应该是一个支持N 级的级联选择框。
UI 设计角度
既然已经确定了要实现 N 级级联选择框,就需要考虑其在各个屏幕尺寸的兼容情况,于是我在组件中引入了 Grid 栅格 。并默认设置了 3 级级联的样式,同时为使用者提供了相应的配置选项,如下:
开发人员角度
我们开发的组件,不止会被我们的团队成员使用,甚至会开源给其他开发者使用。那么,提供给开发者更好的体验就尤为重要。
为了节省开发人员的学习成本,我们可以按照以下思路考虑:
在满足基本需求的前提下,提供尽量少的 API。
为 API 选项提供尽量少的配置项。
为代码,特别是 API 提供尽量好的文档或注释。
定义的 Cascade
组件 Props
示例如下:
可以看到, Props
中只有 dataSource
是必须的。也就是说,如果你对配置项并不了解,组件也只需要最简单的配置,就可以正常工作了,例如:
在使用 TypeScript 时,还需要特别考虑类型匹配的问题。例如可以在使用组件时,传入一个类型,并且在
onChange
事件中如果使用了其他类型, TypeScript 检查就会提示错误,如下面例子中的PCAItem
。
对于级联组件,我们还需要考虑 dataSource 的数据来源可能有两种。
- 组件初始化时,就传入了所有的级联数据,例如 省/地/县/乡层级数据 。对应 Demo 中的“同步级联数据”,以及 Props
中 dataSource
类型定义的 CascadeData<T> | T[][]
。
- 在某些场景下,虽然没有级联选择框存在,但也需要处理树形数据,包括数据的查询和校验等功能,因此将该方法封装到 CascadeData
类中。
- 考虑到树的数据量可能非常庞大,如果在每次选择时都在树中搜索效率较低。因此设计成在组件创建时,直接遍历树中的所有节点,然后将每个层级所有节点的数据都存储在相应的 Map
中,之后就能很方便地查询数据。
- 虽然在组件初始化时遍历所有节点比较耗时,但考虑到用户从进入页面到操作组件有一定时间差,因此我认为这个问题可以忽略。
- 基于以上考虑,你在 Props
中 dataSource
类型中看到的 CascadeData<T>
,就表示直接传入了一个 new CascadeData(treeData)
。而T[][]
就表示直接传入树形数据,由组件内部进行 new CascadeData(treeData)
。
- 组件初始化时,只传入了第一级的选项,之后每级的选项通过前一级所选择的参数,从服务端获取。对应 Demo 中的“异步级联数据”,对应 dataSource
类型中的 T[]
。
- 组件初始化时,只传入第一级的数据,其他级别传入空数组,如:[[{"code":110000,"name":"北京市"}],[],[]]
,组件会渲染出 3 层级联选项。
- 当进行选择时,需要使用者通过 onChange
事件自行更新下一级的数据。也就是说,组件完全放弃了对数据的控制。
与其他组件配合角度
由于该组件需要与 Ant Design 其他组件配合使用,如前面讨论过的 UI 部分,该组件就结合了 Grid 栅格 组件。既保证了该组件在各屏幕宽度下正常显示,又保证了与其他组件的显示一致。
除此之外,还需要考虑与 Form 表单 组件的配合,特别是兼容表单校验功能。
结语
本文通过一个级联组件的设计案例,探讨了如何从四个角度分析,进而设计一个优秀的组件。这 4 个角度分别是:
业务需求角度
UI 设计角度
开发人员角度
与其他组件配合角度
我认为很多时候组件的设计并没有最优解,总是需要根据需求在各种方案中取舍。但只要按照本文提到的 4 个角度进行分析,就能设计出优秀的组件。
版权声明: 本文为 InfoQ 作者【Lee Chen】的原创文章。
原文链接:【http://xie.infoq.cn/article/d6455337e134338fa91bc0829】。文章转载请联系作者。
评论 (1 条评论)