「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战
功能简述
我实现的第一个功能点是简单表单的配置,也就是在页面上配置表单的相关信息,然后生成DSL。
配置表单
如上图所示,在页面的左边,是组件列表。目前只提供了一个组件(table暂时没做完),那就是表单。点击表单按钮之后,则中间的预览部分,会把表单的雏形渲染出来。然后点击表单,则开始编辑表单的相关属性,比如提交的链接、具体的每个字段的控件形式。
可以看到右边的配置区中,有一个Components字段,我们通过这个属性来为表单新增字段。在gif中我新增了一个input,一个number,一个下拉框以及一个textarea。
配置字段
点击input组件,开始配置该字段,输入label为姓名
点击number组件,输入label为年龄
点击select组件,配置label为性别,配置两个option,分别是男、女
点击textarea,配置label为自我介绍
那么一份简单的表单就配置好了
模拟发送请求
紧接着,打开f12,填写表单后点击按钮,可以看到请求按我的设想发送出去了,具体内容如下
curl "https://www.tosubmit.cn/" ^
-H "sec-ch-ua: ^\^" Not;A Brand^\^";v=^\^"99^\^", ^\^"Google Chrome^\^";v=^\^"97^\^", ^\^"Chromium^\^";v=^\^"97^\^"" ^
-H "Accept: application/json, text/plain, */*" ^
-H "Referer: http://localhost:3000/" ^
-H "Content-Type: application/json" ^
-H "sec-ch-ua-mobile: ?0" ^
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36" ^
-H "sec-ch-ua-platform: ^\^"Windows^\^"" ^
--data-raw "^{^\^"0bb8a290-1a89-40ad-939f-8c49227eae5d^\^":^\^"^张^三^\^",^\^"43cc0478-f058-422c-b0fd-a87a569db2a5^\^":^\^"f73df88d-f55a-4050-83b0-430be72cd50c^\^",^\^"873289a0-ebc5-449e-9b5a-73a1a6edcacb^\^":18,^\^"9e0c4dea-95c2-4bc1-8938-e46c72ef134f^\^":^\^"^我^是^张^三^\^"^}" ^
--compressed
接下来看看表单配置这个功能是如何实现的吧
生成DSL
以下就是刚才这份表单的DSL,我采用的是json格式,因为js的变量就是json格式,可以直接使用。
关于DSL的说明
DSL中有几个关键的地方
- uuid 用于唯一标识一个组件
- type 用于标识一个组件的类型,比如form、button、input等
- 整个DSL采用的是树整个数据结构来表示页面,因为html中也是用树这个数据结构
[ { "uuid": "206596c3-5b1d-4c32-9d1a-ac6d3266c5ec", "title": "", "submitUrl": "https://www.toSubmit.cn", "components": [ { "uuid": "0bb8a290-1a89-40ad-939f-8c49227eae5d", "type": 2, "title": "", "label": "姓名" }, { "uuid": "43cc0478-f058-422c-b0fd-a87a569db2a5", "type": 1, "title": "", "single": true, "options": [ { "label": "男", "value": "f73df88d-f55a-4050-83b0-430be72cd50c" }, { "label": "女", "value": "cc75ae1f-5a7c-4a7f-8d57-4e6fccc57d76" } ],
"label": "性别"
},
{
"uuid": "873289a0-ebc5-449e-9b5a-73a1a6edcacb",
"type": 5,
"title": "",
"label": "年龄",
"max": 120,
"min": 0
},
{
"uuid": "9e0c4dea-95c2-4bc1-8938-e46c72ef134f",
"type": 3,
"title": "",
"label": "自我介绍"
}
],
"type": 7,
"button": {
"type": 6,
"text": "Submit"
}
}
]
字段配置
每当一个组件被点击时
- 会根据这个组件的类型,去获取该组件对应的配置表单
- 以表单的形式,把配置展示在右边,供用户配置
- 根据这个组件的uuid去寻找已有的配置,作为表单的初始值展示出来。
- 在配置修改的时候,把修改实时同步回DSL里
短短二三百行代码即可
预览(DSL解析)
从上面可以看到,配置的修改是实时同步到预览功能中的,也就是说每一次配置的变化,都要同步到DSL中,并且修改预览中的效果
解析的原理很简单
- 项目初始化的时候,为每种组件的type都关联对应的组件
- 采用深度优先的算法去遍历树的每个节点,然后根据节点的type属性去获取对应的组件
- 把该组件的配置传入组件中即可
其他
vite
本来计划使用webpack做打包的,可是出于新鲜感使用了vite,确实vite的配置好少而且启动快,非常丝滑,对vite感兴趣的朋友可以去看看我的这篇文章 前端技术储备--vite
Context
目前使用的是react提供的context功能存储页面数据。考虑到后期需要实现的组件非常多,会有多处需要数据分发,因此采用context减少数据分发。目前Context的设计如下
export interface GlobalContextStateProps {
components: ComponentProps[];
editingComponentUuid: string;
registedComponentsMap: Map<ComponentTypes, any>;
}
components字段是DSL数组,类型ComponentProps是所有组件的DSL类型的集合。
registedComponentsMap字段则是组件类型和组件的映射,渲染的时候,会根据DSL中的type字段,来这个map中取对应的组件,从而进行渲染。这里采用了注册模式来实现,目的是后面可以让用户自定义组件,或者通过微前端的方式自定义组件。
总结
综上所述就是用低代码配置表单的过程,如果需要支持更多类型的组件,那么仍然需要人为的开发。
目前获取到了表单的DSL,也能成功的把请求发送出去,但可以看到发送的请求中,内容可读性很差,几乎不可能让外部系统使用
接下来会用低代码平台实现列表页,通过共用DSL的方法来展现本次表单提交的内容
再后面,会用低代码平台实现
- 自定义组件
- 拖拽配置功能
- 表达式解析
感兴趣的朋友可以关注一下