一个简单的联动示例
示例中代码分析
// 以上示例的伪代码实现
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 副作用对象的简单示例
变更前全局数据
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操作如下图,选中车道,更新车道的类型
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
});
}
state.arrowList[state.currentIndex].type = value
procode组件如何接入saveEffect
一个普通的组件是由userInterface 和 api驱动组件内部逻辑的运行;
saveEffect可以通过lowcode的setter层以api(props)的方式动态注入,然后在onChange等对外的接口中抛出即可,完全不影响组件的内部逻辑;
组件抛出value和saveEffect后,系统会自动调用我们开发的解析插件进行数据解析和保存,从而实现组件的"副作用"间联动效果;
《阿里低代码引擎》: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技术背景的人群,旨在提升低代码开发技能,通过场景化的实践,让读者具备系统之间的互联互通能力,逐步成为低代码专家。本书基于”低代码开发师(高级)认证“的课程内容,对应每个场景化的实践,提供了配套的实战指导教程,便于读者根据详细的步骤描述完成应用的创建。
点击阅读原文查看详情。