乐趣区

关于前端:一个低代码拖拉拽的表单编辑器开源咯

编辑器介绍

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

道歉,原谅图有点含糊哈

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], 设 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-plu s 参数是 max, 而在vant 是 count。

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

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

编辑器的两种模式

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

编辑器外部的实在数据是一个tree

默认状况下,编辑器是采纳 布局 字段 不拆散的模式,当然,也反对布局和字段拆散的模式。

  • layoutType1 布局和字段不拆散

    在 PC 端设计表单, 会自适应 mobile 端。

  • layoutType2 布局和字段拆散

    在 PC 端设计表单时,例如将一个字段为 email 的字段放入到 tabs 容器中,切换到 mobile 端,不会同步 tabs 容器的,此时如果在 mobile 新建一个 Collapse 容器,将 email 字段放入其中,切换到 pc 端,是不会同步 Collapse 容器的,对于在一端新增的字段,切换到另一端,会进行两个汇合运算,新增的字段会 push 到画板底部,删除的字段会在布局构造体中删除掉。字段本身的所有属性是同步的。

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

拖拽逻辑

依赖 sortablejs 来实现的,然而用 sortablejs 想做到插入行或者列是不反对的。插入行的时候再包裹一个 inline 容器(元素插入一行会主动包裹一个 inline 虚构容器),当行内惟一元素被挪动走,又得删除 inline 容器,简而言之就是当拖拽一个元素,如果插入行就会包裹一个 inline 容器,如果插入列就插入到 inline 容器下边。
因而写了一个 sortablejs 的插件拦挡了 dragOver 和 drop 事件来实现的。

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

现有性能缺点

  1. 历史记录
  2. 将 tree 构造界面体现进去(外部的数据有了)
  3. GUI 形式管制字段显示与暗藏以及逻辑校验

以上性能接下来开发实现

低代码说白了就是一个堆性能的货色,全副都有了也就能力实现低代码

退出移动版