当前位置: 首页 > news >正文

前端低代码平台

前端低代码平台

原文:
手撸低代码平台搭建(一)走进前端低代码
手撸低代码平台搭建(二)揭秘页面设计器
手撸低代码平台搭建(三)组件间交互的实现
手撸低代码平台搭建(四)组件拖动自由布局的实现
手撸低代码平台搭建(五)自定义组件的实现

1 介绍

1.1 背景

近些年来,随着Saas行业的高速发展,低代码的概念也逐渐流行了起来,而低代码产品也越来越多地出现在我们的身边,像国外的Mendix,国内的宜搭、苍穹、简道云等等。而我(博客作者)司自研的低代码应用构建平台也已服务了十余B端生产项目。基于这种新型的开发方式,图形化的拖拉拽配置界面,并兼容了自定义的组件、代码扩展,确实在B端后台管理类网站建设中很大程度上提升了效率。

1.2 低代码概念

说到低代码,首先我们需要了解一下什么是低代码。

低代码(Low-Code Development,LCD),开发者主要通过图形化用户界面和配置来创建应用软件,而不是像传统模式那样主要依靠手写代码。
低代码开发模式的开发者,通常不需要具备非常专业的编码技能,或者不需要某一专门领域的编码技能,而是可以通过平台的功能和约束来实现专业代码的产出。

这里讲到的“低代码开发模式的开发者”,在低代码开发模式的语境中,“开发者”通常指的是低代码平台的使用者(Citizen Developers),而不是开发低代码平台本身的专业工程师。

低代码的目标是降低开发门槛,让非技术人员也能参与应用构建。例如:一个销售经理可以用微软Power Apps拖拽出一个客户管理系统,无需写代码。一个学校教务员可以用钉钉宜搭设计课程排班应用,仅需配置逻辑。这些用户依赖的是平台预置的模块和自动化代码生成能力,而非自己编写底层代码。

实际上,一个可用的低代码平台的搭建并非难事。首先,我们需要明确,低代码平台解决的最大问题是复用,复用也是目前前端开发中的一个重要课题,特别是当前的主流前端js框架,例如 vue , react 等,都是组件化的开发方式,又如形形色色ui组件库的出现,像 ant-design , element 等都是来解决重复造轮子的问题。

在这里插入图片描述

1.3 简易版低代码平台

我们在前端开发脚手架中,通常会创建一些通用的组件,然后在各个需要这个组件的地方进行引用,来提升开发效率。在脚手架中引用一些ui组件库也是出于这样的目的。
后来,为了防止重复的造轮子,我们通常会对一些成熟的ui组件库中组件根据我们的业务需要进行二次封装,形成一个具有更多功能的区块,例如B端系统中最为常见的列表数据增删改查界面就是这样一个区块。

在这里插入图片描述

我们可以通过一个json数据来描述这个区块,数据大概是下图所示的样子,包含了这个区块的编码,中文名称,以及可传入到这个区块中的属性及初始属性值,例如这个表格包含的列信息、按钮信息等等。而这个json也是低代码平台搭建中最为核心的部分,它在后续介绍的可视化拖拉拽页面设计中扮演极其重要的角色,它是页面设计和页面渲染间串联的纽带。

在这里插入图片描述

当我们展示类似的界面时,只需要在页面文件中引用这个搜索表格模板组件,再把对应的描述json信息传递到组件内就可以了。但是这样似乎还是采用了编码的方式去解决复用问题,距离我们的低代码还有些距离
这时,我们可以将这些可动态控制的组件属性通过在线表单进行填写,存储到数据库中。前端工程中,我们可以进行判断,将使用这个区块模板的页面路由所对应的组件都指向我们封装好的列表增删改查模板。这样,进入到这个页面,我们只需要将之前存储到数据库的区块描述信息通过api接口获取到,再传递到组件内部,将json数据中我们设置的模板属性值赋值到组成模板的各个组件上就可以完成这个模板的渲染了。这也是我们在实现可视化拖拉拽低代码平台之前所使用的方式。这种方式虽然形式上非常简单,却解决了我们组件复用的问题,并且在调整组件属性时只需要通过在线的表单配置,无需打包、发版。这个界面渲染的流程便是低代码平台的核心逻辑:通过组件元数据拼装成一个页面的描述信息,然后通过渲染器组件将描述信息转化页面dom元素。

在这里插入图片描述

我们上面实现的流程是不是除了图形化的配置外,基本可以通过在平台上界面的配置实现一个搜索表格页面的开发了,并且不需要专业的编码技能。
当然,上面的过程中所使用到的模板实际是我们预设好的,只是通过我们传递进去固定属性的不同属性值进行一些差异化的渲染,一些按钮等自定义功能的扩展也只能通过插槽等形式去实现。但当我们想要实现其它模板的界面时,就显得无能为力了,因为组成模板的组件是我们提前预设好的,并不是通过组件像搭积木一样灵活搭建的。

2 低代码开发核心-页面设计器

我们知道,低代码开发平台都是通过拖拉拽可视化的页面设计器进行页面开发的,在这一章节,我们来探索一下页面设计器的实现方式。下图中,我们截取了几款优秀的低代码产品的页面设计器界面。

在这里插入图片描述
可以看到,大多数的页面设计器都包含了如下所示的几个区域:

最上方是操作栏,我们可进行页面的保存、预览、查看json信息、查看代码等操作;
左侧是组件列表,当然也可以添加一些切换,让我们的左侧区域支持查看页面树信息、配置数据源等其他操作;
中间是画布区域,我们可以将左侧的组件拖动到画布中,当然也支持画布中组件的赋值、删除等操作;
右侧是属性配置区域,当我们在画布中选中某个组件时,可以在右侧的属性配置区域罗列出当前组件可支持动态配置的属性,修改了属性后可以在画布中看到对应组件的样式变化。

在这里插入图片描述

2.1 组件列表

首先,我们来看一下左侧的组件列表,列表中的每个组件,我们都需要使用一段json来进行描述,这段json我们将它称之为 元数据,元数据中描述了当前组件的中文名称,在列表中显示的图标及描述,和组件可进行配置的一些动态属性。我们以输入框组件为例,它的元数据大致可以定义为如下的样子:

{code: "MyInput",name: "输入框",desc: "输入框的描述",icon: "input",props: {name: "字段名称",label: "label名称",labelCol: "",wrapperCol: "",required: false,}
}

那么左侧的组件列表实际上就是这样的一个元数据对象组成的数组遍历而来的。

2.2 拖动

再来看一下将左侧组件列表的组件拖动到画布是如何实现的。
拖动又分为顺序排列布局的拖动及自由布局拖动。
顺序排列布局的拖动是指拖动到画布中的组件是自上而下顺序排列的,可以通过拖动调整上下顺序,当然我们也可以增加分栏这样的布局类型组件,实现组件的左右排列;
自由布局拖动是指拖动到画布中的组件位置是自由的,我们松开鼠标的位置,就是这个组件在画布中的位置。
考虑到我们主要服务的是B端项目,需要尽可能使用户体验保持一致,这里我们采用的是顺序排列布局的拖动。这样用户拖动设计出的页面差异性不会太大,页面布局上又相对规整。

vuedraggable

拖动插件由于我们是vue技术栈,选择了vuedraggable插件。像react技术栈也有类似的插件,大家很容易可以搜索到。对于vuedraggable组件的安装及说明这里我们就不赘述了,直接上demo。
vuedraggable
相关文档可见Vue.Draggable的使用

创建js项目→【b站咸虾米】3 Vue CLI脚手架 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例
创建ts项目→【b站ZSEN就是Huzhushan】Typescript入门并在vue项目中使用
项目初始化+路由→【b站咸虾米】4_博客案例 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例 或当时的项目H:\前端\004 Vue2【尚硅谷】\【b站咸虾米】Vue2\code\2 Vue CLI\blog
使用ant design组件库,见组件库引入-1 vue2项目引入ant-design组件库

在这里插入图片描述

上面的demo定义了两个区域,列表区域和目标区域,并定义了两个数组,list1list2。列表区域和目标区域分别使用list1数组和list2数组进行遍历渲染。当我们将列表区域的组件3拖动到目标区域时,我们打印list2变量的数据,就会 发现组件3被复制到了list2中,即复制到了目标区域。细心的小伙伴已经发现,唉!这不就是我们页面设计器组件拖动到画布中的实现方式嘛!是的,设计器中的拖动原理就是这样简单。
支持拖动的区域需要使用<draggable>组件进行包裹,<draggable>组可以添加onAddonStartonEndmove事件回调函数,我们可以在这些事件中添加一些我们需要的逻辑。例如,我们可以在onAdd函数中对我们添加到list2数组列表中的对象动态的添加一个唯一值id,用于我们区分同一个页面拖入两个相同组件的情况。

加唯一id可见前端拖拽-vuedraggable的使用

下面让我们对上面的简单demo稍加改动:

列表区域

  • 我们将list1数组的中的每一项修改为我们之前定义好的组件元数据。
  • 可以将我们定义在元数据中的图标显示在组件列表中,方便我们快速识别出想要拖动到画布中的组件。

第2条先跳过,只是样式问题。

画布区域

  1. 将画布中的组件列表渲染为真实的组件

我们现在知道,画布中的列表实际也是通过组件元数据数组进行渲染的,而每个原数据项都对应了一个真实的组件,这样我们只需要将元数据项替换成UI组件进行渲染就可以了。

注意:可以用动态组件进行优化。

  1. 画布中组件支持删除、复制、拖动操作

在这里插入图片描述
拖动
我们的demo示例中,目标区域list2是支持可拖动排序的。

? 如何实现按住拖动??

复制
我们已经知道,画布中的组件是通过list2遍历渲染出的。当点击复制操作时,只需要将当前被点击复制按钮的组件所对应的元数据添加到list2中就可以了。这里需要注意,在复制元数据的时候,我们需要将id属性值进行累加计算,这样才能区分被复制的组件和复制生成的组件。
删除
同理,删除操作,我们只需要将list2中的组件通过被复制组件id进行过滤就可以了。

上下移动
原理与复制类似。

2.3 嵌套组件

此次不涉及,跳过。

2.4 属性配置区域

其实到这里,很多小伙伴应该已经大致能够推理出属性配置后画布中组件根据配置进行显示的联动是如何进行的了。

原理同样非常简单。我们可以对画布中的组件添加点击事件,当点击某个组件时,我们能够获取到当前点击组件的组件类型,例如输入框、下拉选择等等,针对每一种组件,我们已经提前在元数据中的props属性定义了这个组件能够进行动态控制的参数,我们只需要将这些参数以合适的表单形式展示在右侧的属性配置区域就可以了,例如,按钮组件的props中有一个text属性,用来控制按钮的显示文案,那么我们就在右侧属性控制区域用一个输入框来做为控制这个属性的表单形式,当修改数据时,我们找到list2中该组件所在的元数据对象,然后将该对象中props属性中text属性值修改为输入框中的内容。每个组件都会接受这个组件对应的元数据props参数,然后根据参数值进行渲染。例如按钮组件,现在按钮的文案时,我们可以使用props.text进行显示。

2.5 操作栏区域

从上面的文章中可以看出,一个页面实际就是用一段带有层级结构的json来进行描述的。

保存
保存时实际就是将这段json进行保存操作,我们可以将json存储到数据库中。

预览
在上面讲解画布区域时,我们已讲到组件如何通过json进行渲染。预览以及真实的页面渲染实际和画布中组件的展示实现原理完全一致。
其中的区别有两点:
(1)画布中的组件不支持交互操作,这里,我们需要屏蔽画布中组件的交互操作。我们可以通过css中的after伪类,设置content""来实现。
(2)画布中的组件需要包裹一个div,这个div包含了复制、删除等功能。

其它功能
其实整个页面设计器的核心就是json,其它各种功能也都是围绕json进行。我相信大家仔细读完这篇文章,再看其它功能时也可以推断出其实现的原理。

这部分先跳过

2.6 后记

好啦,至此页面设计器的组件列表、画布和属性配置三个区域的联动我们就都实现了。
目前,我们的页面设计器设计出的界面还是静态的,画布中的组件也都是独立而毫无关联的。在真实的业务场景,组件间的通讯是非常常见的。在后面的章节中,我们讲会重点介绍低代码中如何进行 组件间通讯 的配置。感兴趣的小伙伴可以 点一波关注 啦。我们一起手拉手,搭建自己的低代码平台~!

3 组件间交互的实现

3.1 前言

我们在上一篇文章中主要介绍了低代码平台的页面设计器相关的一些功能原理,打通了页面设计器顶部操作栏、左侧组件列表,中间画布、右侧属性配置四个部分的关系。
能够实现组件列表的展示、组件到画布的拖动,属性配置修改对组件渲染效果影响,并说明了页面设计器中设计好的页面是如何进行渲染的。

虽然我们看起来实现了通过组件拖拉拽完成页面的开发,但是目前的页面还是无法进行使用的,这是因为页面中的组件都是相互独立而又没有关联的。实际页面中的绝大多数组件都需要进行相互通讯。例如当我们点击某个按钮时,需要获取到表单组件的表单值进行提交;又比如我们点击某个按钮会弹出一个弹窗。我们这一篇文章将重点分析一下在低代码开发中组件间交互的实现方式。

3.2 事件

3.2.1 事件的分类

我们主要依托于事件来进行组件间的交互。为了满足组件与组件、组件与系统、组件与服务端的交互,我们大致可以将事件分为三个类别:

  • 组件方法:每个组件都会暴露出一些方法供其他组件进行调用。例如表格组件,我们可以暴露出查询表格数据方法;弹窗组件,可以暴露打开、关闭方法等等。
  • 系统动作:有些方法并不属于某个组件,而是系统全局的动作,例如路由的跳转、全局的消息提示、页面加载动画的显隐等等。
  • API调用:这一类主要用于处理组件与服务端的交互,也就是服务端api接口的调用。
3.2.2 事件的定义

系统动作和API调用的定义相对比较简单,我们可以在vue组件的methods中进行方法的定义,例如我们可以定义一个request方法用于api的调用,request中调用了我们使用axios封装好的统一的请求方法,request方法支持传入apiurlmethodapi参数等信息。这两类事件为全局事件,我们可以将这些方法放到mixins中,然后在各个组件中进行引用。

而对于组件方法,我们需要将组件暴露的方法定义在各个组件的methods中,并在组件加载时进行方法的监听。

window.vm.$on(`${id}-${methodName}`, params => {// TODO
})

在组件销毁时取消监听。

window.vm.$off(`${id}-${methodName}`)

还记得吗,我们在上一篇文章页面设计器设计好页面时,生成的组件元数据项中附加了一个id字段,而这个字段在事件监听中也起到了重要作用,能够有效的避免页面中相同的组件重复的触发事件。

做好事件的监听后,我们就可以使用emit关键字触发事件了。

componentMethod(id, methodName, params) {window.vm.$emit(`${id}-${methodName}`, params);
}

在事件配置的时候只需要调用methods中的componentMethod方法就可以了。

3.2.3 事件的配置

上一篇文章中我们讲到,设计器中的每个组件都对应了一段json元数据,我们某个组件的属性时,会到设计器属性配置区域进行表单值的修改,从而修改整个页面json中该组件所对应的这一段json,同理,当我们进行某个组件的事件配置时,也会对组件的事件属性进行赋值,我们将这个事件属性定义为event。属性值为一段js函数字符串,如下图所示。

在这里插入图片描述
这样,我们执行事件时,只需要将函数字符串转换为函数进行调用就可以了。

对于代码编辑器插件,推荐一下ace,相对比较成熟,功能丰富,上手简单。这里我们就不做详细的介绍了,有兴趣的小伙伴可以到ace官网查看。

3.2.4 事件的执行

上面讲到,我们将事件配置成了一段函数字符串,那如何来执行呢,相对对于小伙伴来说并不难,我们可以使用eval或者Function去执行,这里我们选择使用Function

首先我们定义一个字符串函数解析方法funcStrParse

function funcStrParse(funcStr) {return Function("'use strict';return (" + funcStr + ")")();
}

这个方法的参数是一段函数字符串,返回值是一个函数。执行时,我们只需要调用funcStrParse返回的函数即可。

funcStrParse("这是一段函数字符串")(ctx);

眼尖的小伙伴可能发现了,我们执行这段函数时,传入了一个ctx参数,实际上,这个ctx参数就是vue组件中的this。上文中我们讲到,我们会在vue组件中的methods中定义一些系统方法(通过mixin引用)和组件方法。这样,我们在代码编辑器中编写事件时,就可以通过ctx变量调用vue组件methods中的方法了。

3.2.4 事件的参数

可能有些小伙伴还是有些疑问。我们已经可以通过配置去调用组件中的方法了,那么我们如何获取到其它组件中的参数呢?我们知道,组件参数的传递方式有很多,最基本的就是通过props属性或者通过project/inject进行传递。考虑到设计器中的组件繁多,并且每个组件都有独特的互不相同的组件参数,这样会导致组件标签中传递的属性过多,并且取用十分不方便。我们需要将各个组件暴露的参数放到一个公共的地方,这样在使用的时候就非常方便了。这个公共的地方定义到vuex中的store中还是比较合适的。我们以页面为单位注册storemodule,将所有的组件变量都存到所在页面modulestatepageParams对象变量中。如下图所示。其中id就是组件的id,也就是在pageParams变量中,我们以组件的idkey,以组件的参数集合对象为value。这样,我们就可以直接在事件配置中进行使用了。

在这里插入图片描述

3.3 后记

页面设计器中如何实现组件间的交互,我们就分享完啦。小伙伴们有没有更好的实现方式呢?欢迎评论交流。在后面面的章节中,我们会介绍一下当页面设计器中提供的组件不足以支撑我们的页面设计时,我们是否能够通过自定义组件的方式来补充左侧的组件列表,拖拽到画布中,实现我们的需求呢?感兴趣的小伙伴可以关注一波啦!

3.4 个人总结

本节适合结合实践练习理解。

3.4.1 功能梳理

首先,总结目前组件的功能如下:

  • 登录组件

    • 整体背景图
    • 左上角人物图
    • 登录注册背景色
    • 登录注册字体颜色
    • 登录注册位置
  • 图片组件

    • 图片
  • 任务组件

    • 任务名称
    • 按钮名称
    • 任务配置
3.4.2 完成一个完整功能

先完成一个基本的任务组件,再使用本节事件的方式去优化。

目前的效果(2025/11/8)
在这里插入图片描述

支持选择和回显
在这里插入图片描述

3.4.3 梳理适合使用事件总线的功能点

目前add页面,画布任务组件,配置任务组件,选择任务弹窗之间的功能:

  • 1 add页面
    • 1 更新画布组件配置(由配置任务组件3.1触发)
  • 2 画布任务组件
    • 1 回显(表面不涉及逻辑,实际需要在画布组件更新配置1.1后重新渲染)
  • 3 配置任务组件
    • 1 更新选中组件配置(触发1.1)
      • 1 修改表单内容
      • 2 新增任务
      • 3 选择关联任务
    • 2 打开任务选择弹窗
    • 3 关闭任务选择弹窗
  • 4 选择任务弹窗
    • 1 确定选择任务(触发3.1.3)
    • 2 关闭选择任务弹窗 (触发3.3)
    • 3 选择任务
3.4.4 使用事件总线实现修改配置刷新画布组件

新增eventbus。这部分直接去看代码实现。

event-bus的方式省去了子组件emit给父组件和父组件接受emit事件处理函数的部分,但事件处理逻辑依然需要。

3.4.5 事件配置

事件配置,如配置刷新数据的方法。实际发现刷新登录组件的逻辑与任务组件类似,目前可以不处理。

个人觉得事件配置方式比较灵活,但是比较麻烦,需要函数转字符串,如此代码可读性不高,且出错不易定位,先不用。

3.4.6 vuex状态管理

可以使用vuex管理项目状态(本节3.2.4也是这么建议的),但这个改动对整体功能没有影响,这里不再实现。

3.4.7 功能演示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4 组件拖动自由布局的实现

不涉及,跳过。

5 自定义组件的实现

稍微看看,还没有到如此程度。

http://www.dtcms.com/a/588899.html

相关文章:

  • 八字排盘原理
  • 40.交叉编译
  • RT-Thread Studio开发环境搭建
  • jdbc基础(连接篇)
  • 免费云服务器网站有哪些为什么手机进网站乱码
  • 从入门到精通 LlamaIndex RAG 应用开发
  • 算法基础篇:(五)基础算法之差分——以“空间”换“时间”
  • 潍坊中企动力做的网站怎么样wordpress显示摘要
  • leetcode1771.由子序列构造的最长回文串长度
  • 【JUnit实战3_31】第十九章:基于 JUnit 5 + Hibernate + Spring 的数据库单元测试
  • 双11释放新增量,淘宝闪购激活近场潜力
  • MySQL快速入门——内置函数
  • 中小网站建设都有哪些网易企业邮箱申请
  • 预测电流控制在光伏逆变器中的低延迟实现:华为FPGA加速方案与并网稳定性验证
  • C语言--文件读写函数的使用
  • 网站的网站维护的原因可以做公众号的网站
  • 使用waitpid回收多个子进程
  • leetcode1547.切棍子的最小成本
  • ThinkPHP8学习篇(十一):模型关联(一)
  • 深入理解Ribbon的架构原理
  • 力扣(LeetCode)100题:3.无重复字符的最长子串
  • 前端接口安全与性能优化实战
  • ssh网站怎么做wordpress搬家_后台错乱
  • LangChain V1.0 Messages 详细指南
  • 网站商城微信支付接口申请软件开发人工收费标准
  • 代码生成与开发辅助
  • claude code访问本地部署的MCP服务
  • 学习笔记8
  • Vue编程式路由导航
  • android contentprovider及其查看