背景:我之前写过一篇文章:《Liteflow逻辑编排可视化设计》,分享了我们对LiteFlow这个规则引擎的逻辑可视化设计,而我们这个可视化项目的目标不仅仅只是实现LiteFlow的逻辑可视化,而是实现LiteFlow的逻辑可视化编排。
接下来,我将通过系列文章的形式,进行LiteFlow逻辑可视化编排设计与实现的开发经验分享。
《LiteFlow逻辑可视化编排设计与实现》会以系列文章的形式,有步骤、有重点地分享我们对LiteFlow逻辑可视化编排的实现,目前该系列文章有如下4篇:
- LiteFlow逻辑可视化编排设计与实现 01-先导篇
- LiteFlow逻辑可视化编排设计与实现 02-数据模型篇(Model)
- LiteFlow逻辑可视化编排设计与实现 03-视图呈现篇(View)
- LiteFlow逻辑可视化编排设计与实现 04-操作逻辑篇(Control)
以下是《LiteFlow逻辑可视化编排设计与实现 03-视图呈现篇(View)》的文章正文。
03-视图呈现篇(View)
回顾一下我们在《先导篇》中提到过的内容,作为一名前端开发,我们需要特别关注的要素有三个------数据(Model)、视图(View)和逻辑(Control),即"MVC"------我接下来也是使用"MVC三要素"的知识框架来进行LiteFlow逻辑可视化编排系统的拆解、组合、设计和实现的:
在《数据模型篇》中,我们完成了EL表达式的操作符(Operator)的建模工作,最终我们将EL表达式建模成了由ELNode组成的一棵树:
接下来,我们将使用AntV X6的节点(Node)和边(Edge)进行ELNode的可视化呈现,即通过Nodes & Edges实现LiteFlow的逻辑可视化设计:
1、心法口诀:"两点一线"
如果把LiteFlow的逻辑可视化的设计心法总结一下,那就可以总结为一句口诀:"两点一线"。因为我们从要素的拆解来看,一张图本质上无外乎就是「两点一线」------即节点和连线,以及在节点和连线上的文字标签。
我们对LiteFlow的逻辑可视化设计,就是通过"节点"和"连线"的组合进行逻辑可视化呈现的。比如下面是LiteFlow逻辑编排的根节点Chain的可视化设计:
LiteFlow逻辑编排的根节点Chain的可视化设计包括:
- 两点:即一个"开始节点"和一个"结束节点";
- 一线:在"开始节点"和"结束节点"之间画一条线。
通过AntV X6进行"两点一线"的代码实现也相对简单,一个"两点一线"的参考实现如下:
typescript
// 1. 首先:创建一个开始节点
const start: Node = Node.create({
shape: 'liteflow-start',
attrs: {
label: { text: '开始' },
},
});
// 2. 然后:创建一个结束节点
const end: Node = Node.create({
shape: 'liteflow-end',
attrs: {
label: { text: '结束' },
},
});
// 3. 最后:创建开始节点和结束节点之间的连线
Edge.create({
shape: 'edge',
source: start,
target: end,
});
事实上,上面的代码就是我们对LiteFlow逻辑可视化的实现代码,其他操作符(包括串行编排THEN、并行编排WHEN、条件编排IF等等)也是使用了同样"两点一线"的思路来实现的:
以下是我们分别对LiteFlow各个逻辑编排的可视化设计和实现。
2、逻辑可视化编排设计与实现
2.1 串行编排:THEN
1、文本(Liteflow EL)表达式
如果你要依次执行a,b,c,d四个组件,你可以用THEN
关键字,需要注意的是,THEN
必须大写。
typescript
<chain name="chain1">
THEN(a, b, c, d);
</chain>
2、JSON表示形式
typescript
{
"type": "THEN",
"children": [
{ "type": "NodeComponent", "id": "a" },
{ "type": "NodeComponent", "id": "b" },
{ "type": "NodeComponent", "id": "c" },
{ "type": "NodeComponent", "id": "d" },
]
}
3、通过节点模型进行表示
typescript
┌─────────────────┐
┌──▶│ NodeOperator │
│ └─────────────────┘
│ ┌─────────────────┐
├──▶│ NodeOperator │
┌─────────┐ ┌─────────────────┐ │ └─────────────────┘
│ Chain │───▶│ ThenOperator │──┤ ┌─────────────────┐
└─────────┘ └─────────────────┘ ├──▶│ NodeOperator │
│ └─────────────────┘
│ ┌─────────────────┐
└──▶│ NodeOperator │
└─────────────────┘
4、可视化设计与实现
2.2 并行编排:WHEN
1、文本(Liteflow EL)表达式
如果你要并行执行a,b,c,d四个组件,你可以用WHEN
关键字,需要注意的是,WHEN
必须大写。
typescript
<chain name="chain1">
WHEN(a, b, c, d)
</chain>
2、JSON表示形式
typescript
{
"type": "THEN",
"children": [
{ "type": "NodeComponent", "id": "a" },
{ "type": "NodeComponent", "id": "b" },
{ "type": "NodeComponent", "id": "c" },
{ "type": "NodeComponent", "id": "d" },
]
}
3、通过节点模型进行表示
typescript
┌─────────────────┐
┌──▶│ NodeOperator │
│ └─────────────────┘
│ ┌─────────────────┐
├──▶│ NodeOperator │
┌─────────┐ ┌─────────────────┐ │ └─────────────────┘
│ Chain │───▶│ WhenOperator │──┤ ┌─────────────────┐
└─────────┘ └─────────────────┘ ├──▶│ NodeOperator │
│ └─────────────────┘
│ ┌─────────────────┐
└──▶│ NodeOperator │
└─────────────────┘
4、可视化设计与实现
2.3 选择编排:SWITCH
1、文本(Liteflow EL)表达式
如果,根据组件a,来选择执行b,c,d中的一个,你可以如下声明:
typescript
<chain name="chain1">
SWITCH(a).to(b, c, d);
</chain>
2、JSON表示形式
typescript
{
"type": "SWITCH",
"condition": { "type": "SwitchComponent", "id": "x" },
"children": [
{ "type": "NodeComponent", "id": "a" },
{ "type": "NodeComponent", "id": "b" },
{ "type": "NodeComponent", "id": "c" },
{ "type": "NodeComponent", "id": "d" },
]
}
3、通过节点模型进行表示
typescript
┌─────────────────┐
┌──▶│ NodeOperator │
│ └─────────────────┘
│ ┌─────────────────┐
├──▶│ NodeOperator │
┌─────────┐ ┌─────────────────┐ │ └─────────────────┘
│ Chain │───▶│ SwitchOperator │──┤ ┌─────────────────┐
└─────────┘ └─────────────────┘ ├──▶│ NodeOperator │
│ └─────────────────┘
│ ┌─────────────────┐
└──▶│ NodeOperator │
└─────────────────┘
4、可视化设计与实现
2.4 条件编排:IF
1、文本(Liteflow EL)表达式
typescript
<chain name="chain1">
IF(x, a);
</chain>
2、JSON表示形式
typescript
{
"type": "IF",
"condition": { "type": "IfComponent", "id": "x" },
"children": [
{ "type": "NodeComponent", "id": "a" },
]
}
3、通过节点模型进行表示
typescript
┌─────────────────┐
┌──▶│ NodeOperator │
┌─────────┐ ┌─────────────────┐ │ └─────────────────┘
│ Chain │───▶│ IfOperator │──┤ ┌─────────────────┐
└─────────┘ └─────────────────┘ └──▶│ NodeOperator │
└─────────────────┘
4、可视化设计与实现
2.5 循环编排:FOR
1、文本(Liteflow EL)表达式
typescript
<chain name="chain1">
FOR(f).DO(THEN(a, b));
</chain>
2、JSON表示形式
typescript
{
"type": "FOR",
"condition": { "type": "ForComponent", "id": "f" },
"children": [
{
"type": "THEN",
"children": [
{ "type": "NodeComponent", "id": "a" },
{ "type": "NodeComponent", "id": "b" },
]
}
]
}
3、通过节点模型进行表示
typescript
┌─────────────────┐
┌──▶│ NodeOperator │
┌─────────┐ ┌─────────────────┐ │ └─────────────────┘ ┌─────────────────┐
│ Chain │───▶│ ForOperator │──┤ ┌─────────────────┐ ┌──▶│ NodeOperator │
└─────────┘ └─────────────────┘ └──▶│ ThenOperator │──┤ └─────────────────┘
└─────────────────┘ │ ┌─────────────────┐
└──▶│ NodeOperator │
└─────────────────┘
4、可视化设计与实现
2.6 循环编排:WHILE
1、文本(Liteflow EL)表达式
typescript
<chain name="chain1">
WHILE(x).DO(THEN(a, b));
</chain>
2、JSON表示形式
typescript
{
"type": "WHILE",
"condition": { "type": "WhileComponent", "id": "x" },
"children": [
{
"type": "THEN",
"children": [
{ "type": "NodeComponent", "id": "a" },
{ "type": "NodeComponent", "id": "b" },
]
}
]
}
3、通过节点模型进行表示
typescript
┌─────────────────┐
┌──▶│ NodeOperator │
┌─────────┐ ┌─────────────────┐ │ └─────────────────┘ ┌─────────────────┐
│ Chain │───▶│ WhileOperator │──┤ ┌─────────────────┐ ┌──▶│ NodeOperator │
└─────────┘ └─────────────────┘ └──▶│ ThenOperator │──┤ └─────────────────┘
└─────────────────┘ │ ┌─────────────────┐
└──▶│ NodeOperator │
└─────────────────┘
4、可视化设计与实现
以上是我们《LiteFlow逻辑可视化编排设计与实现 03-视图呈现篇(View)》的内容,我们完成了使用AntV X6的节点(Node)和边(Edge)进行ELNode的可视化呈现,即通过Nodes & Edges实现LiteFlow的逻辑可视化设计。