Ant Design 作为中后台中最常用的组件库,几乎覆盖了所有的使用场景。 但是我们在写中后台的时候是在写什么呢?在很多时候我们其实是根据后端的定义的数据结构来进行表单,表格和详情页的搭建。
interface Contract {
/** contractId */
contractId?: string;
/** 文案名字 */
displayName?: string;
/** 图标链接 */
iconLink?: string;
/** 发放开始时间 */
startTime?: string;
/** 发放过期时间 */
expiredTime?: string;
}
上面的数据就是一个例子,我们需要一个配置后台来处理以上的的数据,我们需要用很多组件。
- Table 展示配置列表
- Form 新建数据
- Input 输入文本
- DatePick 输入日期
- Image 预览图片
- Upload 上传图片
- Descriptions 展示详情
- moment 的格式化文案
在所有的项目中我们几乎都会做这样的事情,几乎每个列配置都需要一个 render 来进行定义。所以我们希望可以用一套配置,或者说一些预设来解决常见的问题。
🌊 场景化的抽象
既然我们与后端映射的时候时根据一个简单的数据结构来实现的,那么我们前端是不是也可以实现一个基础的组件来和数据库的数据进行映射的。
- String 映射为 Input
- Int 映射为 number
- timestamp 映射为 DatePick
但是很快就有了新的问题。基础数据类型只有三种,string
,number
,number
但是仅仅 antd 就有 39 个 录入和展示相关的组件。如果使用相同的枚举方式任何组件都需要打很多很多孔。
其中尤其以 String 最为复杂,手机号和邮箱就已经几乎是两种展示方式,涉及到脱敏,校验规则,点击行为等多个方面。即使是一个简单的 password 展示,也有好几副面孔。
所以 ProField 决定从场景的发放时来进行抽象,不抽象输入框,数字输入框这样的最基础的类型,这方面 Ant Design 已经做的很好了,拥有了很强的团队维护。ProField 从更上层去封装一个类型,这样让我们有了一个巨大的优势,大部分时候我们可以用一个字符串来描述一种类型,而不是像 UISchema 一样,充满了 冗余 和 为了收敛样式而进行的配置。 schemaSsSSSchema
更棒的是因为我们的 ProField 是同时包含了 编辑 和 只读模式,所以你只需要一个配置就可以转化两种形态。
基础抽象已经完成,那我们就可以来搭建更大的组件了,Table 就是一系列只读 ProField 的集合,Form 就是一系列的编辑 ProField 的组合。他们是如此的相似,我们只需要修改 ProField 的状态和布局就可以用同一套抽象来实现 Table 和 Form,并且预设了相同的样式。
我们在做一个小小的样式排列组合,一个在中后台中最常见的表格就诞生了,由于的表格和表单公用了抽象,我们可以根据下面的列来生成上面的表单,只要一份配置就可以上下对应,生成同样的查询表单。
基于同样的功能,我们实现了可能是西湖区最好用的可编辑表格,因为组成 Table 的 ProField 本身就带有编辑的功能,可编辑表格要做的只是控制哪个Field 进入编辑模式,同时依托于 ProField 的抽象,我们可以用 valueType 在初始化的时候就定义好如何编辑这一列,大大节省了开发效率。
🌈 模板组件
ProField 解决了数据展示和录入的问题,但是很多时候我们都是在组合布局和请求数据。所以我们推出了模板组件的概念,我们期望一个页面由一个组件组成。一个列表页应该只需要一个 ProTable 就可以完成表单的所有操作。
组件和页面的区别是什么呢?这是一个抽象过的页面开发流程
在这个开发流程中,我们都会在组件中加入业务逻辑 ,然后封装成业务组件在组合一个页面。业务组件明显是更高级的抽象。但是业务组件很多都涉及到不同业务的独有的逻辑,那么有没有什么东西是任何业务都是共有的?
这就是我们模板组件做的事情 网络请求 和 布局 , 已 Table 为例除了单元的样式抽象,与网络请求的交互也是非常复杂的地方,现在有些 hooks 可以提供部分的逻辑自动处理。但是 Table 中还有分页筛选和查询表单的数据需要处理和同步。
为此 ProTable 提供了 request 的 API, 这个接口提供了一个通用的抽象来解决所有的表格的查询问题。