从rookie的视角看低代码平台
前两天刚出的软考成绩,结果既在我意料之中又在我意料之外,上午最有把握的选择题部分没过结果晚上最没信心的论文居然过了,至于案例则是意料之中的不及格。虽然考后就知道这次过不了了,但是还是不免有点失望,不过好在考前我最不看好的论文居然成了我最后一块遮羞布,不至于让我的成绩太过难看。
想想花了这么长时间备考也不能什么都没留下,于是就想写一篇文章说说我的软考论文主题:低代码。老实说我也不知道为什么我的论文能过,当时四个题目一个不会,就随便选一个直接写了,最终硬凑了2500结束。言归正传,下面讲讲我做低代码时的理解。
低代码项目最开始在互联网上火起来应该在2019年前后,由于我所在公司有一个自己研发的低代码平台,并且我的项目业务也涉及到了这个项目,所以就和低代码结缘,低代码的主要作用就是让开发者们尽量以最低的代码编程量来完成一个页面的制作,减少前端页面开发的时间。其实就是将预先封装好的组件放置到组件栏里,用户通过拖拽组件到canvas面板上,同时对应组件封装的信息添加到schema源码中来实现一个页面的快速制作。本篇文章就拿我所在公司的低代码项目为例。
项目是基于vue2+antDesign,下面说说项目的核心功能页面,也就是页面配置,主要分为组件栏、canvas面板、组件配置栏三个部分,如下图
组件栏
组件栏中集成了我们封装好的所有组件,先说一下制作一个组件的流程,在特定的组件components目录下创建以你要制作的组件名称为名字的文件夹,在该文件夹下按照特定的结构创建文件,如下图所示。
之所以要严格按照这种结构创建目录是由于我们封装的组件是借助webpack的api:require.context来全局注册的。
require.context是一个 webpack 的 api ,通过该函数可以获取一个上下文,从而实现工程自动化(遍历文件夹的文件,从中获取指定文件,自动导入模块)。
在前端工程中,如果一个文件夹中的模块需要频繁引用时可以使用该中方式一次性引入
使用代码:
const asyncComponent = require.context('@/components',true,/[A-Z]\w+\.vue$/,'lazy')
asyncComponent.keys().forEach(fileName => {
const [version,componentName] = fileName
.split('/')
.splice(-2)
.map(n => n.replace(/\.vue$/,''))
Vue.component(`${componentName}-${version}`,
() => asyncComponent(fileName)
.then(resolve => resolve.default || resolve))
})
这样就实现了封装的组件的全局注册。
解决了组件注册剩下的就比较简单了,通过index.js开放出我们所封装组件的基本信息,如标题,icon,版本等。在统一展示到组件栏中即可。
组件配置栏
组件的配置栏里是我们封装的组件里为了提高组件可用性而开放出来的一些兼容配置,最基础的选项如按钮的样式,字体大小等之类的。配置项封装需要在上面组件的目录结构下增加配置文件,如图:
总共增加了两个文件,分别是配置项的代码文件和组件的默认配置数据文件,配置项中代码双向绑定config.js中的数据,组件代码watch监听config中数据的改变。这样修改配置栏里的数据,便等同于修改config.js中数据,组件监听到数据修改,也会动态改变其展示数据。
组件配置栏除了基础的样式配置意外还有事件配置,如按钮的点击事件,输入框的聚焦等,同时事件又分为同步事件和异步事件,既需要调用接口(异步)和无需调用接口(同步)。
同步事件比较好处理,在触发自定义事件后直接运行编写的脚本就好,异步事件脚本分为前置脚本和后置脚本,即接口调用前执行的脚本和接口调用完成后的脚本。
最后,在index.js文件开放出的数据中添加config.js中的数据。
canves面板
虽然说是canves面板,但其实并没有用到canves,就只是一个div,给面板和组件栏绑定鼠标事件,实现拖拽的效果。用到的事件:mouseenter、mouseleave、dragstart、dragover、dragleave、drop
画布上添加组件的同时数据也会同步到schema源码里,有时候修改组件配置也可以直接通过修改schema源码不用通过配置栏去修改。
面板的功能操作有保存、前进、后退、清空、主题切换等
前进和后退是通过监听页面组件数据改变,每改变一次就将该组件数据存入vuex中的快照数组保存起来并,每当前进和后退就从快照数组拿页面组件数据。
代码如下:
init_historyRecord: (state) => {
state.historyRecord = {
actionPoints: [], // 快照数组
step: 0,
maxStack: 15,
updateTime: ''
}
},
push_record: (state, data) => {
if(data.length === 0) {
return
}
const curTime = Date.now()
const record = state.historyRecord
record.actionPoints.push(JSON.parse(JSON.stringify(data)))
record.step++
// 长度超出了
if (record.actionPoints.length > record.maxStack) {
record.actionPoints.shift()
record.step--
}
record.updateTime = curTime
},
// 后退
undo_record: (state) => {
const record = state.historyRecord
if (record.step <= 1) { return }
record.step--
record.updateTime = Date.now()
state.renderComponentList.list = record.actionPoints[record.step - 1]
},
// 前进
redo_record: (state) => {
const record = state.historyRecord
if (record.step + 1 >= record.actionPoints.length) { return }
record.step++
record.updateTime = Date.now()
state.renderComponentList.list = record.actionPoints[record.step]
},
最后,schema源码编辑器使用了VSCode的monaco-editor,VSCode编辑器底层用的就是monaco-editor实现的,非常好用的,给大家安利一下。