查看原文
其他

基于Vue3 的可视化编辑器Everright-formEditor开源

刘海峰 前端早读课 2023-04-21

前言

把技术转换成产品的能力,真好。本文由 @刘海峰投稿分享。

正文从这开始~~

编辑器介绍

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

抱歉,原谅图有点模糊哈

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

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

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

  1. 灵活的拖放功能:通过拖拽便可决定一个字段插入行还是列,无需布局容器

  2. 提供多种字段:单行文本、邮箱、身份证号、手机号、网址、多行文本、数字、单选框、多选框、时间、日期、评分、开关、滑块、Html 编辑器、级联、上传文件、签名、省市区

  3. 布局字段:栅格布局、表格布局、标签页、折叠面板、分割线

  4. 内置了国际化:中文和英文

  5. 内置两种模式:字段与布局不分离、字段与布局分离

  6. 编辑器、预览器和配置面板都可以单独使用,可以根据实际需求选择性单独使用配置面板,满足不同场景下的需求

以下是编辑器部分预览图

编辑器界面

预览器 pc 界面

预览器 mobile 界面

属性面板界面

内部实现原理

Field

Field 作为元素之一

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

注意右上角的的白色图案,表示这个 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。

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

  • 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 的元素和实例来实现的。

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

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

现有功能缺陷

  1. 历史记录

  2. 将 tree 结构界面体现出来 (内部的数据有了)

  3. GUI 方式控制字段显示与隐藏以及逻辑校验

以上功能接下来开发完成

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


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存