前言

每当提起低代码,很多人都会下意识的出现过激反应,吐槽低代码都是**,唯恐避之不及。可能大部分人觉得低代码就是替代手写代码,对于程序员来说这是不可接受的。其实低代码表述的含义非常宽泛,我相信很多人可能都在低代码平台中受益过,而且确实可以提升效率。像原型工具(Figma)、建站平台(WebflowFramer)、BI 报表(Power BILooker Studio)、3D 模型搭建(SplineWomp)、动画编辑器(Rive)等等,这些都是非常有名的一些在线工具。

言归正传,本文并不是为了介绍低代码平台,也不想评价低代码的好坏,只是想聊一聊低代码平台中 GUI 的设计思路和实现方式。

Acrodata GUI 是一款适用于低代码平台的轻量级 GUI 库,现已开源。

GitHub: https://github.com/acrodata/gui

Playground: https://acrodata.github.io/gui/playground

什么是 GUI

GUI 翻译为图形用户界面,是指采用图形方式显示的计算机操作用户界面。在前端编程中,我们一般很少使用 GUI 这样的描述,所以很多人会错误地认为 GUI = UI library。

那么到底什么是 GUI 呢?为了便于理解,我们可以参照前端项目中比较有名的 GUI 项目 dat.gui。做过 3D 可视化或者熟悉 ThreeJS 的朋友一定非常熟悉这个库。dat.gui 的主要用途就是将配置项转换成图形化控件,方便调试参数。

除了 dat.gui 之外,还有其它几款 GUI 项目也做得不错,tweakpanelil-guileva

低代码平台中的配置栏

对于使用过低代码平台或者开发过类似产品的朋友来说,低代码平台的布局已经司空见惯,在布局的右侧通常都是配置栏。当然,我们使用的很多软件也是如此。随便贴几张主流工具的截图。





首先说一点,并不是每一款低代码产品都需要 GUI 生成配置,比如第一张截图 Webflow,它的所有组件的配置项都是一样的(全部是 CSS 的可视化配置),这种情况直接写一个公共组件可能更简单。

但是像第三张截图 Looker Studio 这样的产品,每一种图表组件的配置都不一样,同时还允许用户自定义组件,那么这类产品就非常需要一套灵活易用的 GUI 库了。

在 Acrodata GUI 的文档站首页,我用 GUI 创建了一个稍微复杂的 CSS 渐变生成器,它和低代码平台中的配置栏非常类型,欢迎把玩尝试。

查看 CSS 渐变生成器源码

轻量级 GUI 的设计思路

由于低代码平台的特殊性和复杂性,GUI 库在设计的时候必须要保证能组合出任意数据结构,同时还要简单易用。

基于 JSON 的配置项

为了支持自定义组件,GUI 库更适合采用 JSON 数据进行配置。这和上面提到的 GUI 库在使用上有很大的不同,我们以 dat.gui 和 Acrodata GUI 为例说明。

假设某个组件的配置项如下:

const options = {
content: 'Hello world',
opacity: 0.3,
visible: false,
}

dat.gui 的用法如下:

const gui = new dat.GUI();

gui.add(options, 'content');
gui.add(options, 'opacity', 0, 1).step(0.1);
gui.add(options, 'visible');

虽然 dat.gui 的用法很简洁,但是这种函数式的声明方式并不适合动态组件,同时也不利于数据保存。

而在 Acrodata GUI 中的用法则是这样的:

<gui-form [config]="config" />
const config = {
content: {
type: 'text',
name: 'content',
default: 'Hello world'
},
opacity: {
type: 'slider',
name: 'opacity',
min: 0,
max: 1,
step: 0.1,
default: 0.3
},
visible: {
type: 'switch',
name: 'visible',
default: false
},
}

上面的 GUI 的配置项和组件的配置项的结构是一样的,只需要将 options 中每个字段的值转换成 UI 控件的 JSON 声明即可。

查看更多基础控件示例

嵌套的数据结构

如果要保证 GUI 可以生成任意数据结构,需要设计五种基础数据(string, number, boolean, object, array)的 JSON 配置项的定义格式。上面的例子中已经展示了三种基本数据类型的定义方式

在 Acrodata GUI 中 object 的定义如下:

{
"size": {
"type": "group",
"name": "Size",
"children": {
"width": {
"name": "Width",
"type": "number",
"default": 1920,
"suffix": "px"
},
"height": {
"name": "Height",
"type": "number",
"default": 1080,
"suffix": "px"
}
}
}
}

最后一种数组类型是最复杂也是最繁琐的。常用数组包含基本数据数组和对象数组,同时每种数组还要支持数组项的动态删减。

下面是一个可动态删减的对象数组的定义方式:

{
"series": {
"type": "tabs",
"name": "Series",
"default": [
{ "id": 1, "name": "bar" },
{ "id": 2, "name": "foo" }
],
"template": {
"name": "No.<%= i + 1 %>",
"children": {
"id": {
"type": "number",
"name": "ID"
},
"name": {
"type": "text",
"name": "Name"
}
}
}
}
}

如果对象数组的数组项不相同,则必须搭配 tab 类型来定义:

{
"misc": {
"type": "tabs",
"name": "Misc",
"children": [
{
"type": "tab",
"name": "Full Name",
"children": {
"firstName": {
"type": "text",
"name": "First Name",
"default": "James"
},
"lastName": {
"type": "text",
"name": "Last Name",
"default": "Bob"
}
}
},
{
"type": "tab",
"name": "Contact",
"children": {
"phone": {
"type": "text",
"name": "Phone",
"default": "5550100"
}
}
}
]
}
}

查看更多组合控件示例

有了上述五种基础控件之后,通过嵌套组合就可以生成任意数据结构了。

JSON Schema 的局限性

为什么不使用 JSON Schema 呢? 很多人可能觉得使用 JSON Schema 定义 JSON 数据会更规范也更通用。这种想法是有道理的,但是 JSON Schema 也有一定的局限性。

首先 JSON Schema 只能定义字段的数据类型,但是无法定义字段的 UI 类型,所以部分使用 JSON Schema 的动态表单方案还会加上 UI Schema,比如 react-jsonschema-form

另外 JSON Schema 的格式较为复杂,组件的配置项与 JSON Schema 的映射关系非常不直观。

基于响应式表单构建 GUI

Acrodata GUI 是基于 Angular 的响应式表单构建的,核心代码只有大约 200 行(查看源码)。

为了方便在模板中遍历数据,首先需要将 GUI config 对象转换成数组,同时使用响应式表单的 registerControlFormGroup 的实例中注册所有表单控件。然后在模板中使用响应式表单的指令 formGroupNameformControlNameformArrayName 绑定不同 type 的控件就可以了。

Acrodata GUI 使用 Angular Material 作为基础组件库,所有样式和组件都是分模块导入,所以不会产生冗余的代码,其它组件库也可以使用。

开始使用 GUI 组件

<gui-form [config]="config" [model]="model" [form]="form" />

config 表示 GUI 的 JSON 配置项,不同类型的控件的配置项稍有不同,详见文档。除了使用 default 定义控件的默认值之外,也可以使用 model(表单值,等同于组件的配置项 options)来定义或更新表单的默认值,这得益于 Angular 响应式表单的 patchValue 方法。

如果你需要监听表单的状态或者值变更,可以使用 form 参数,它可以追踪表单的所有状态变化。

form = new FormGroup({});

this.form.valueChanges.subscribe(v =>{...});
this.form.get('opacity').valueChanges.subscribe(v =>{...});

总结

虽然上面展示的 GUI 功能很强大,但是 GUI 和动态表单并不能完全划等号,也不是所有的配置项都适合使用 GUI。因为 GUI 的控件类型有限,而且其本身没有复杂的逻辑,所以在低代码平台中要有取舍的使用 GUI 配置。

如果你喜欢 Acrodata GUI 或者有更好的想法,欢迎和我交流!

低代码之光!轻量级 GUI 的设计与实现的更多相关文章

  1. 技术调研,IDEA 插件怎么开发「脚手架、低代码可视化编排、接口生成测试」?

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 不踩些坑,根本不是成熟的码农! 你觉得肯德基全家桶是什么?一家人一起吃的桶吗,就那么 ...

  2. 【摸鱼神器】UI库秒变低代码工具——表单篇(一)设计

    前面说了列表的低代码化的方法,本篇介绍一下表单的低代码化. 内容摘要 需求分析. 定义 interface. 定义表单控件的 props. 定义 json 文件. 基于 el-form 封装,实现依赖 ...

  3. 为企业应用开发提速,写给企业IT部门的低代码开发基础知识

    简介:应用程序开发长期以来一直是IT部门和业务部门面临的问题. IT部门总是被新的应用程序需求弄得不堪重负.他们不可能完成业务部门想要完成的每一个项目. 同时,业务部门的用户厌倦了等待,并开始完全绕过 ...

  4. 开源低代码平台开发实践二:从 0 构建一个基于 ER 图的低代码后端

    前后端分离了! 第一次知道这个事情的时候,内心是困惑的. 前端都出去搞 SPA,SEO 们同意吗? 后来,SSR 来了. 他说:"SEO 们同意了!" 任何人的反对,都没用了,时代 ...

  5. 低代码开发Paas平台时代来了

    概述 **本人博客网站 **IT小神 www.itxiaoshen.com 低代码理论 概念 低代码开发基于可视化和模型驱动的概念,结合了云原生和多终端体验技术,它可以在大多数业务场景中,帮助企业显著 ...

  6. 2022了你还不会『低代码』?数据科学也能玩转Low-Code啦! ⛵

    作者:韩信子@ShowMeAI 数据分析实战系列:http://www.showmeai.tech/tutorials/40 机器学习实战系列:http://www.showmeai.tech/tut ...

  7. 微服务低代码Serverless平台(星链)的应用实践

    导读 星链是京东科技消金基础研发部研发的一款研发效能提升的工具平台,面向后端服务研发需求,尤其是集成性.场景化.定制化等难度不太高.但比较繁琐的需求,如服务前端的后端(BFF).服务流程编排.异步消息 ...

  8. 游戏引擎/GUI的设计与实现-序

    几年前写<嵌入式GUI FTK设计与实现>,没写几篇就停止更新了.当时自己研究过MicroWindows, X Window, DirectFB, GTK+和Android的GUI,又写过 ...

  9. 基于低代码平台(Low Code Platform)开发中小企业信息化项目

    前言:中小企业信息化需求强烈,对于开发中小企业信息化项目的软件工作和程序员来说,如何根据中小企业的特点,快速理解其信息化项目的需求并及时交付项目,是一个值得关注和研讨的话题. 最近几年来,随着全球经济 ...

  10. MATLAB(3)——GUI界面设计入门

    作者:桂. 时间:2017-03-01  18:43:35 链接:http://www.cnblogs.com/xingshansi/articles/6485688.html 声明:转载请注明出处, ...

随机推荐

  1. 通过snmp获取设备每个接口的配置IP地址,网段信息和VLAN接口号

    第一部分,观察通过snmp OID能获取的信息,对信息进行关联. 1.通过 snmp获取到接口IP地址和掩码信息,发现IP地址作为索引值: 2.每个IP地址的索引,都可以关联到接口的索引 3.每个接口 ...

  2. 安装软件提示 "无法完成操作, 因为文件包含病毒或潜在的垃圾软件" 如何处理

    在Windows端安装一些小众电脑软件的时候,经常会遇到无法安装的问题,比较常见的情况是会提示 "无法完成操作, 因为文件包含病毒或潜在的垃圾软件", 或者提示"不能执行 ...

  3. 小知识:Docker环境缺少vi命令,如何解决

    docker exec可以使用--user参数指定root用户,进入安装vi即可: [opc@oci-001 ~]$ docker exec -it --user root testdb bash b ...

  4. SQL查询中的小技巧:SELECT 1 和 LIMIT 1 替代 count(*)

    前言 在写SQL查询时,常规做法是使用SELECT count(*)来统计符合条件的记录数. 然而,在某些情况下,我们只关心是否存在符合条件的记录,而不需要知道具体的记录数. 为了优化性能,可以改用使 ...

  5. 两个例子带你入门 Disruptor

    Disruptor 是英国外汇交易公司 LMAX 开发的一个高性能队列.很多知名开源项目里,比如 canal .log4j2. storm 都是用了 Disruptor 以提升系统性能 . 这篇文章, ...

  6. DESTOON做中英双语言(多语言)切换版本具体详解

    第一次发原创好激动,该注意点什么? 在开发过程中用户有许多要求,比如这个多语言切换就是一个需求. 首先讲解一下DESTOON(DT)后台系统如何做这个中英.甚至多语言切换的这个功能. DT本身不自带多 ...

  7. 文心一言 VS 讯飞星火 VS chatgpt (107)-- 算法导论10.1 5题

    五.用go语言,栈插入和删除元素只能在同一端进行,队列的插入操作和删除操作分别在两端进行,与它们不同的,有一种双端队列(deque),其插入和删除操作都可以在两端进行.写出4个时间均为 O(1)的过程 ...

  8. 前端框架——Vue2

    文章目录 初识Vue 模板语法 数据绑定 el与data的两种写法 理解MVVM 数据代理 事件处理 计算属性 监视属性 绑定样式 条件渲染 列表渲染 收集表单数据 过滤器 内置指令 自定义指令 生命 ...

  9. 爽。。。一键导出 MySQL 表结构,告别手动梳理表结构文档了。。。

    背景 系统需要交付,客户要求提供交维材料,包括系统的表结构,安排开发人员进行梳理,效率比较慢,遂自己花点时间捣鼓一下,发现有此插件,记录一下方便与同事分享 前提条件 必须有 go语言环境,有的话直接看 ...

  10. 从一次Kafka宕机说起(JVM hang)

    一.背景 时间大概是在夏天7月份,突然收到小伙伴的情报,我们线上的一个kafka实例的某个broker突然不提供服务了,也没看到什么异常日志,反正就是生产.消费都停了.因为是线上服务,而且进程还在,就 ...