地图作业平台低代码实战(搭建能力提升)
背景
1、地图数据作业平台由大型的WebGIS"综合作业"逐步转换为人机结合,所见即所得的流水化"简单作业";
问题与分析
// 以上示例的伪代码实现class Main extends PurComponents {constructor() {this.state = {A: '',B: '',C: '',}}// 响应逻辑handleAChange = (e) => {// 1.数据源筛选const { target: { value } } = e;// 2.双向绑定,组织数据结构let stateOptions = {A: value;};// 3.数据联动if (value === '1') {stateOptions = {...stateOptions,B: '',C: '',}}// 4.更新数据this.setState(stateOptions);};// UI组件render() {<div className="pic-wrapper"><PicPlayer ... /></div><div className="task-oper"><Text>标牌是否是施工场景</Text><ButtonGroup onChange={(e) => this.handleAChange(e)} />...<ButtonGroup disabled={A !== '2'} ... />...<ButtonGroup disabled={B !== '2'} ... /></div>... bla bla bla}}
- 由上方伪代码可以看到,一个车间的实现分为:UI + 逻辑
- 在可视化搭建中,UI部分和简单交互由组件内部实现,跨组件的逻辑部分则由事件回调实现,回调函数可以拆分为以下 四部分主体功能和相关概念 :
-
数据筛选 :从函数参数中筛选需要的数据(涉及事件驱动的概念)
-
双向绑定: 受控组件由外部数据驱动,状态变化后需要更新依赖的数据源(受控组件,双向绑定,不可变原则)
-
数据联动: 其它数据的更新,组件间的联动通信;(业务逻辑)
-
数据更新: 前端框架Api;
- 针对事件驱动中回调函数中的数据筛选能力,我们开发了数据筛选器,在设计页面的组件设置器中用树形结构静态声明函数参数,用户只需选择对应的参数即可实现类似数据解构和赋值的功能
- 针对双向绑定,数据联动,immutable不可变原则,我们约定了简洁的数据存储语法,并针对此语法开发了特定的语法的解析插件,具体设计如下:
- 页面中一个组件状态变更触发联动其它组件状态变化的场景,我们认为这是一个组件的状态变更过程的"副作用"saveEffect;
- 每一条"副作用"包含三部分,分别是源数据,目标数据,转换逻辑,以上面联动为例:源数据A, 目标数据B, 转换逻辑是当A为1时,B清空, 对应数据结构是:
一个"副作用"对象由三部分构成{// 源数据fromPath: 'e.target.value',// 目标数据toPath: 'state.B',// 转换逻辑formatFunc: 'function switchStoreValue(value, state) { return A == '1' ? '' : state.B };'}
- 我们在低代码组件中提供了saveEffect设置器, 让用户自行选择"副作用"的源数据、确定目标值,并书写转换逻辑,这部分逻辑被注入到组件中,组件在回调函数中将输出值 和 saveEffect对象同时抛出,最终交由我们的语法解析插件解析并执行,实现组件联动;
- 针对数据更新,我们认为用户根本无须关注框架层的API,所以开发了自动绑定设置器@ali/lowcode-setter-a-event-setter 会将组件的回调函数绑定到saveState全局函数中,在saveState全局函数中自动执行数据更新操作, 以下是一条联动"副作用"示例
以上saveEffect对象,用户仅需指定 目标值 路径,插件会自动解析路径的语法,并将activeKey所有父级结构生成新的引用,最后自动调用setState实现组件更新;// saveEffect 副作用对象的简单示例// 变更前全局数据state = {temp: {imageIndex: 0,},workResult: {imageList: [{attr1: 1,attr2: 2,},...]}}// 用户确定的saveEffect对象{// 源数据fromPath: 'value' // 1// 目标数据toPath: 'workResult.imageList[state.temp.imageIndex].activeKey';// 默认值,用户无须书写formatFunc: 'function switchStoreValue(value, state) { return value }';}// 无转换逻辑,则经过插件解析后会生成以下结构并merge到state中{temp: {imageIndex: 0,},workResult: {imageList: [{attr1: 1,attr2: 2,...activeKey:1},...]}}
使用效果
使用saveEffect设置器节省代码的前后对比,以引导线内容车间为例,我们需要为一个引导线方向赋值一个属性,UI操作如下图,选中车道,更新车道的类型
使用saveEffect对象结合语法解析插件,使用者仅需在目标值中填写一句即可(大部分情况下转换函数是不用修改的);function handleButtonGroupClick(value) {// 获取当前选中的箭头选项const { arrowList, currentIndex } = this.state;const currentArrow = arrowList[currentIndex];// 数据更新const newArrow = {...currentArrow,type: value};// 数据不可变;const newArrowList = arrowList.slice(0, currentIndex).concat([newArrow]).concat(arrowList.slice(currentIndex + 1));// lowcode API更新数据this.setState({arrowList: newArrowList});}
对应的setter UI 如下:state.arrowList[state.currentIndex].type = value
- 一个普通的组件是由userInterface 和 api驱动组件内部逻辑的运行;
- saveEffect可以通过lowcode的setter层以api(props)的方式动态注入,然后在onChange等对外的接口中抛出即可,完全不影响组件的内部逻辑;
- 组件抛出value和saveEffect后,系统会自动调用我们开发的解析插件进行数据解析和保存,从而实现组件的"副作用"间联动效果;
总结与展望
这篇文章主要介绍了我们通过自定义插件,设置器,组件标准化等一些方式,降低了作业平台内组件间联动,数据处理的难度,实现了让非研发同学可以独立搭建我们小粒度车间的目标。除此之外,我们还在可视化方面开发了 for循环组件 , if/else 等逻辑组件 ,意图用可视化组件的方式实现一些基本的 模板语法 ,结合我们开发的 车间模板 ,使得用户只需在页面内完成少量定制逻辑可以实现车间开发。 未来我们计划在低代码平台中加入 逻辑编排能力 ,最终实现 逻辑代码的图形化表达 ,进一步支持更为复杂的车间搭建。
参考
《阿里低代码引擎》:https://lowcode-engine.cn/docV2/intro 《设置器扩展》:https://lowcode-engine.cn/docV2/cl03wo_nmhznb 《setter开发调试》:https://lowcode-engine.cn/docV2/ulvlkz 《物料规范》:https://lowcode-engine.cn/material 《阿里低代码引擎使用文档》:https://www.yuque.com/lce/doc往期推荐
低代码开发是指无需编码或通过少量代码,就可以快速生成应用程序的新型开发方式。“低代码开发师(高级)”针对有IT技术背景的人群,旨在提升低代码开发技能,通过场景化的实践,让读者具备系统之间的互联互通能力,逐步成为低代码专家。本书基于”低代码开发师(高级)认证“的课程内容,对应每个场景化的实践,提供了配套的实战指导教程,便于读者根据详细的步骤描述完成应用的创建。
点击阅读原文查看详情。