乐趣区

关于前端:试着换个角度理解低代码平台设计的本质

本文会次要分享本人对低代码平台的了解,从多个角度和问题去看低代码平台的设计。我感觉 低代码平台的外围在于模型设计,包含控件模型、组件模型、画布模型等等。心愿看完本文,你能晓得:

  • 低代码平台外围的底层逻辑是什么?
  • 为何常见低代码平台都蕴含“控件区”、“布局区”和“属性编辑区”?
  • 低代码平台的控件、组件、画布的实质是什么?
  • 如果让低代码平台反对跨平台?
  • 如何让低代码平台反对自定义数据源?

那让咱们开始吧​。

一、你所看见过的低代码平台

近几年国内纷纷呈现各种低代码产品,在 降本增效提质 方面施展重要作用。低代码平台的业务场景波及越来越宽泛:自定义表单、页面制作、流动详情页、工作流场景、数据报表、大屏数据报表、数据表格、白板笔记等等。对应成熟的低代码产品也十分多:阿里宜搭、腾讯云搭、百度爱速搭、轻流、Jeecg Boot、码良等等。

下图腾讯开源的 tmagic 平台,是咱们最常见的低代码平台布局形式:

(本图来自:tmagic)

其中包含三个外围模块:

  • 控件区:展现平台内反对的控件,用户通过拖拽控件到布局区,即可展现控件对应的 UI 组件款式;
  • 布局区:用来承载控件对应的 UI 组件,用户能够对每个 UI 组件进行布局,并且直观查看页面成果;
  • 属性编辑区:用来展现该控件反对的配置内容,能够更加灵便的对每个控件对应的 UI 组件进行自定义设置。

所以,为何各个产品纷纷采纳这类布局?

二、换个角度思考低代码平台设计

咱们在解决问题时,常常会应用两种办法:

  • 自顶向下法:从指标登程,拆解和细化问题,找到解决办法;
  • 自底向上法:汇总各种零散信息,失去正确办法和论断。

咱们试着用 自顶向下法 思考一下低代码平台的设计:

通常在团队确定是否须要开发低代码平台前,都会通过头脑风暴、灵感探讨、业务须要状况剖析,而后确定开发低代码平台的原始需要。

假如这么一个场景:

掘金社区的主页布局比拟繁多,当须要减少或调整局部模块时,须要改变我的项目代码、打包、提测、公布,这时候如果能有一个主页设计平台,让经营人员自在调整页面布局,还能够针对不同节日、流动调整出不同主页布局。

基于这样的场景,咱们应用 自顶向下法,从指标登程,拆解和细化问题,找出解决办法。

1. 确定指标

咱们的指标需要是可能灵便的布局社区主页:

2. 拆解和细化问题

如果要实现灵便布局的掘金主页,就须要将主页中的模块抽成每个独立控件:

如果每个控件须要可能灵便配置,咱们还须要可能配置控件的任意局部:

3. 找到解决办法

依照前两个步骤的剖析,咱们能够确定大抵解决办法:

  1. 须要实现一个反对自在拖拽布局的设计平台;
  2. 该平台反对拖拽不同控件到页面中;
  3. 每个控件反对不同的自定义配置;
  4. 设计器反对导出页面构造,渲染器反对渲染页面内容。

于是咱们就有了上面的计划:

这样是为什么常见低代码平台都会有“控件区”、“布局区”和“属性编辑区”。

通常交互逻辑如下:

  1. 从「控件区」拖拽一个控件进入「布局区」,将控件渲染成对应组件;
  2. 选中组件,在「属性配置区」显示该组件所有反对配置的属性;
  3. 批改「属性配置区」的属性,更新「布局区」中该组件的款式。

这是最简略的一个流程。

三、思考更加通用的低代码模型

低代码平台创立的页面,实质上不肯定是单个页面,也能够是由多个页面组成的一个 Web 利用,因而,咱们能够把下面示例,形象成更加通用的低代码平台模型:

该模型定义了低代码平台创立的页面构造,最终的渲染是由对应渲染器渲染页面。

这就有点 VNode 树的滋味啦。

(图片起源:https://v3.cn.vuejs.org/)

对于 Vue 而言,外围要解决的就是“如何创立 VNode”和“如何渲染 VNode”。

接下来咱们通过 TypeScript 接口模式定义上面的构造:

能够发现,单页利用和多页利用的关系在于,通过为单页利用减少 path配置,将多个单页利用组合成多页利用。

到这里咱们就有一个更加通用的低代码模型,并且应用 TypeScript 接口定义了每一层的构造。

能够看出:低代码平台的外围在于模型设计,定义每个局部的模型。

四、控件区的控件没这么简略

1. 控件是什么?

控件实质是一个 规范的 JSONSchema 对象,用来形容最终渲染进去的组件。在低代码平台中,将控件拖拽到布局区才会显示对应的组件款式。

以「用户信息控件」为例:

const UserInfo = {
    name: '用户信息控件',
    type: 'UserInfoComponent', // 指定渲染的组件名称
    config: [
        {
            label: '头像',
            type: 'input',
            value: 'https://a.com',
        },
        {
            label: '昵称',
            type: 'input',
            value: 'pingan8787'
        }
    ]
}

通常咱们会在控件对象中定义一个 type(也可能是其余名称),用来 指定控件所渲染的组件名称 。比方 Vue 中,就能够通过该 type 值,应用动静组件 <component :is={type} /> 模式动静渲染组件。

控件就好比是组件的说明书,只是对组件进行形容,形容了它是什么样子,有哪些行为、配置等信息。

2. 控件还有什么长处?

控件定义成 规范的 JSON 对象 ,还有其余长处没比方: 能够实现控件跨平台适配,在不同平台 / 组件库渲染不同的组件。指标平台只需依照模型渲染不同组件即可。

3. 控件如何实现动静加载近程组件?

常见的计划是为每个控件指定近程组件的地址(如设置 path 属性),当控件开始被拖拽时,发送申请获取近程组件:

const UserInfo = {
    name: '用户信息控件',
    type: 'UserInfoComponent', // 指定渲染的组件名称
    path: 'https://a.com/UserInfoComponent.js', // 近程组件的地址
    config: [
        {
            label: '头像',
            type: 'input',
            value: 'https://a.com',
        },
        {
            label: '昵称',
            type: 'input',
            value: 'pingan8787'
        }
    ]
}

以 Vue 为例,当获取到近程 Vue 组件后,能够通过 Vue 提供的动静组件进行注册和应用。

残缺过程如下:

  1. 开始拖拽「控件区」控件,并发动申请,从服务端获取近程组件;
  2. 当获取到近程组件后,注册到我的项目中;
  3. 松开控件,渲染组件内容到「画布区」。

当然,思考到编辑器的性能优化,防止每次拖拽都发送申请获取组件文件,咱们能够这样优化:

  • 应用申请缓存,如果是反复申请,则从缓存读取上次申请后果;
  • 对罕用根底组件事后发送申请并保留本地;
  • 本地缓存已申请的组件,下次申请雷同组件,则读取缓存后果;
  • 等等

五、画布区的画布也没这么简略

1. 画布是什么?

画布的实质也是一个 规范 JSON 对象,它是咱们最终要渲染页面所用的数据源,通常蕴含整个页面的构造和配置信息。当拖拽控件进入画布和更新组件配置时,会更新画布。

咱们依据掘金主页,简略结构一个模型(不思考多页面状况):

const Juejin = {
    title: '掘金主页',
    favicon: './favicon.icon',
    components: [
        {
            name: '用户信息控件',
            type: 'UserInfoComponent',
            config: [
                {
                    label: '头像',
                    type: 'input',
                    value: 'https://a.com',
                },
                {
                    label: '昵称',
                    type: 'input',
                    value: 'pingan8787'
                }
            ]
        }
    ]
}

在下面模型中,定义了画布中的每个组件,寄存在 components数组下,每个组件都蕴含各自的 nametypeconfig等信息,在渲染器渲染时,就能够:

  • 依据 type渲染配置区的组件;
  • 依据 label 渲染配置区表单的 label 文本;
  • 依据 value渲染配置区表单的值。

2. 画布还有丰盛的配置

对于画布模型,最重要的应该是组件列表,即后面的 components数组,对于每一个组件,最次要的信息包含:

  • 事件模型信息:蕴含该组件绑定的一些事件(如事件名称等);
  • 动画模型信息:蕴含该组件绑定的一些动画成果(如旋转、放大等);
  • UI 款式模型信息:蕴含该组件绑定的一些 UI 款式(如背景色、字号等);
  • 数据 / 数据源模型信息:蕴含该组件绑定的一些数据源相干的配置(如数据源接口地址等)。

以「事件模型信息」为例,当页面中配置了一个按钮,这个按钮往往能够做如下事件:

  • 关上链接;
  • 关上弹框;
  • 关上 APP;
  • 刷新页面;
  • 发送申请;
  • 等等。

此时,该按钮可触发的行为十分多,如果把每个事件处理逻辑都写在组件中,会使得组件臃肿无比,且耦合在组件中,可维护性差。

为了升高组件和事件处理逻辑之间的耦合度,咱们能够在组件和事件处理逻辑两头减少一层,即事件总线:

实现通用组件派发事件到事件总线,不同的业务场景监听事件,执行具体的事件处理逻辑。

通过事件总线,将派发事件和监听事件的单方相互解耦,实现解耦后,还可能实现 跨平台 的性能,对于派发雷同的事件,只须要在不同平台监听该事件,实现不同的解决逻辑即可

六、数据源设计

所谓「数据源」即低代码平台中数据起源,通常依照业务需要能够将数据源分为两类:

  • 静态数据源:数据绑定在页面配置中,在最终成果页时,间接应用页面配置中的数据,无需通过接口获取数据;
  • 动静数据源:个别是保留数据源的接口在配置中,不绑定数据,在最终成果页时,客户端须要再发送申请获取数据。

1. 静态数据源的过程

在低代码设计平台中,平台先申请数据,用户抉择其中指定数据,保留在页面配置中。

比方当咱们已有 banner 列表接口,须要抉择其中一张,增加到布局区中:

步骤如下:

  1. 用户在「控件区」抉择「轮播控件」,拖入「布局区」;
  2. 点击「布局区」中「轮播控件」的组件,关上「属性配置区」;
  3. 抉择「属性配置区」中「抉择 banner」,平台发送申请,从服务端获取 banner 列表;
  4. 关上「抉择 banner 弹框」,展现 banner 列表,用户抉择所需 banner 图片;
  5. 点击「确定」,敞开「抉择 banner」弹框,并在「布局区」的「轮播控件」组件插入该笔数据,实现抉择。

用户在「抉择 banner」弹框中,选中指定的数据,保留到页面配置中,当拜访最终生成成果页,会间接显示出已抉择的 banner 图片。

2. 动静数据源的过程

动静数据源相比静态数据源,会更加灵便,用户指定数据源接口后,当接口数据变动,最终成果页能够动静扭转展现的内容。

比方当咱们已有 banner 列表接口,能够在治理后盾增加不同的 banner,最终成果页可能展现新的 banner,而用户只需在设计时,指定 banner 列表接口即可:

步骤如下:

  1. 用户在「控件区」抉择「轮播控件」,拖入「布局区」;
  2. 点击「布局区」中「轮播控件」的组件,关上「属性配置区」;
  3. 抉择「属性配置区」中「配置 banner」,配置“接口地址”和“转换规则”;
  4. 抉择实现,点击「确定」,敞开「抉择 banner」弹框,将配置的“接口地址”和“转换规则”数据保留在「布局区」页面配置中,配置实现。
  5. 当用户拜访最终成果页时,页面会先调用配置的“接口地址”获取近程的 banner 列表;
  6. 将接口返回的数据通过“转换规则”,将接口返回的数据转换成组件所有的数据格式。

这样就实现了最终成果页可能每次都展现最新的数据,实现齐全动静。

3. 减少数据源适配器

当须要对两个耦合度较高的逻辑进行解耦,能够通过减少适配器办法进行解耦,因而在数据源这边也能够减少适配器对「UI 组件」和「接口数据」进行解耦。

现实状态应该是:

  • UI 组件只对外裸露组件反对的配置和办法,而无需关注是什么业务应用该组件;
  • 接口数据也无需关注数据被什么组件应用。

于是,咱们别离为「静态数据源」和「动静数据源」减少了数据适配器,流程如下:

  • 静态数据源

在第 4 步时,接口返回的数据会通过「数据适配器 1」,将接口数据转换为「抉择 banner」弹框组件对立的参数。同理,第 6 步将弹框组件返回的数据结构,通过「数据适配器 2」转换为「banner 组件」所需参数的数据结构。

  • 动静数据源

在第 6 步时,接口返回的数据会通过「数据适配器」,将接口数据转换为「banner 组件」对立的参数数据结构。

其实总结一下,就是通过各种数据适配器,将各种起源的数据结构转换为组件的参数模型即可。益处也很显著:

  • 更换数据源时,只须要依照组件参数模型对接接口,实现各种数据适配器,无需改变原有逻辑;
  • 更换 UI 组件库时,也只须要依照组件参数模型对接 UI 组件,实现各种数据适配器,无需改变原有逻辑。

4. 总结数据源设计

依照后面的计划,咱们对数据源就有了次要方向,其次要的外围在于:通过定义组件接口模型和适配器模型,咱们能够很容易的开发任意组件和适配器,依照定义的模型,其余开发者也能很不便的开发。

七、总结

低代码平台作用在于降本增效提质,外围在于模型设计,升高各个性能点的耦合度,让平台反对跨平台

本文通过 自顶向下法 ,介绍低代码平台的设计思路, 从指标登程,拆解和细化问题,找到解决办法。前面针对低代码平台的几个外围模块逐个剖析本人的了解,着重介绍了外围模块的模型设计和配置。

本文是本人通过几个低代码平台实战后的了解和总结,心愿对各位有所帮忙,低代码平台的将来有限可能。

这是我第一次写低代码相干的文章,如有谬误,欢送斧正~~

退出移动版