一个低代码拖拉拽的表单编辑器,开源咯!

2023-04-25 13:49:04 +08:00
 zhuizhuidea

编辑器介绍

先来个图,有个初步的认识

抱歉,原谅图有点模糊哈

github: https://github.com/Liberty-liu/Everright-formEditor

demo: https://everright.site/zh-cn/module/formEditor/introduction.html

Everright-formEditor是一个基于 vue3 的可视化编辑器,依赖于element-plusvant进行开发。内部提供了适配器进行参数转码。

  1. 灵活的拖放功能(通过拖拽便可决定一个字段插入行还是列,无需布局容器)
  2. 提供多种字段(单行文本、邮箱、身份证号、手机号、网址、多行文本、数字、单选框、多选框、时间、日期、评分、开关、滑块、Html 编辑器、级联、上传文件、签名、省市区)
  3. 布局字段(栅格布局、表格布局、标签页、折叠面板、分割线)
  4. 内置了国际化(中文和英文)
  5. 内置两种模式:字段与布局不分离、字段与布局分离
  6. 编辑器、预览器和配置面板都可以单独使用,可以根据实际需求选择性单独使用配置面板,满足不同场景下的需求

多图预警!!!多图预警!!!多图预警!!!多图预警!!!多图预警!!!多图预警!!!

编辑器界面

预览器 pc 界面

预览器 mobile 界面

属性面板界面

内部实现原理

Field

Field作为元素之一

在一个 form 编辑器里边,主要操作的是一个元素,布局容器(也是元素之一)则是作为Field的承载。用下图表示一个FieldField自身会有很多的属性。

注意右上角的的白色图案,表示这个Field内部属性由两个管道的输入来共同决定。

  1. 来自canvas 面板canvas 面板下面的选区(Selection)
  2. 来自属性面板配置属性

Field经过用户的 click 或者拖拉拽的方式塞入Canvas 画板

Canvas

用下图表示一个Canvas 画板

Canvas 画板内部的数据用一个二维数组表示Array[r][c],设 r 为行,c 为列,是不是有了一点 table 的味道了,事实上如 table 一样的,内部可以无限嵌套的(布局容器是可以嵌套)。

当一个元素被插入Canvas 画板元素会自动被 选区(Selection) 包裹。

选区(Selection)

用下图表示一个选区(Selection)

图中白色区域表示slot,元素被放置在这个地方。

选区(Selection) 提供是否可以被拖拽、删除、复制、调整大小、选中父级的功能。

当选中元素时,会在Canvas 面板上被高亮显示。

Config 面板

用下图表示一个Config 面板

用于配置字段属性。

当选中元素时,Config 面板会显示被选中元素的自身的全部属性

数据流动图

结合以上示意图,将用户的行为用下图示意

再加一段文字描述方便理解

  1. 当用户通过 click 或者拖拉拽的方式将一个元素拖入到画板当中,编辑器会自动为该元素包裹一个选区(Selection)
  2. 当用户选中选区的时候,Config 面板会显示被选中元素的自身的全部属性
  3. 用户通过Config 面板或者选区(Selection) 修改元素属性的时候,数据会同步到Canvas 画板,实现所见即所得

适配器(Adapter)

用下图表示一个适配器(Adapter)

由于 pc 依赖 element-plus ,mobile 依赖 vant ,它们之间交集部分的功能参数有些是不一样的,适配器(Adapter) 就是做这个体力活的。

举个栗子

Rate 评分这个组件想设置一下星星⭐️的数量,在element-plus 参数是 max,而在vant是 count 。

下面插入一点点代码示意一下适配器所做的事情

if (!isPc) {
  result.count = options.max
} else {
  result.max = options.max
}

编辑器的两种模式

再回顾一下在编辑器内部流动的主要数据是元素元素分为字段布局容器

编辑器内部的真实数据是一个tree

默认情况下,编辑器是采用布局字段不分离的模式,当然,也支持布局和字段分离的模式。

以上无论哪种模式,导出的数据都会把Field抽离出来的,与后端而言,他们更关心的是字段而非是一个 tree 。

拖拽逻辑

依赖sortablejs来实现的,但是用sortablejs想做到插入行或者列是不支持的。插入行的时候再包裹一个 inline 容器(元素插入一行会自动包裹一个 inline 虚拟容器),当行内唯一元素被移动走,又得删除 inline 容器,简而言之就是当拖拽一个元素,如果插入行就会包裹一个 inline 容器,如果插入列就插入到 inline 容器下边。 因此写了一个 sortablejs 的插件拦截了 dragOver 和 drop 事件来实现的。

当拖拽的时候会一直触发 dragOver 事件,根据当前鼠标的 x/y 判断在 target 元素的四个方向决定是插入行还是列,判断四个方向是根据斜率计算的,贴一张图比较容易理解。挡 drop 的时候记录最后一次 dragOver 的元素和实例来实现的。

开发环境下有一个 node 的服务

在开发环境下内置了一个后端服务,基于 node 写的,数据库是 SQLite (只需要生成一个数据库文件就好,无需常规数据库搭环境那么复杂,微信 App 的聊天记录就是用这个数据库存储的) ,一个编辑器最终是要提交到数据库中的,所以有一个 crud 方便开发。

现有功能缺陷

  1. 历史记录
  2. 将 tree 结构界面体现出来(内部的数据有了)
  3. GUI 方式控制字段显示与隐藏以及逻辑校验

以上功能接下来开发完成

低代码说白了就是一个堆功能的东西,全部都有了也就才能实现低代码

1184 次点击
所在节点    前端开发
4 条回复
coolair
2023-04-25 13:57:53 +08:00
没有动态行的子表单吗?
zhuizhuidea
2023-04-25 13:59:15 +08:00
@coolair 目前没有做了,现在再做一个可视化控制字段校验和显隐,开发完这个会去开发子表单吧
yuxu952
197 天前
可以实现根据响应的字段,进行映射在页面自动展示列表吗
yuxu952
197 天前
逻辑控制那块,好多 bug 啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/935337

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX