节点图系统
节点图系统是 MdrFrontEngine 独特的可视化编程系统,让你通过连接节点来构建业务逻辑,无需编写复杂的代码。
概述
节点图采用数据流编程范式,每个节点代表一个操作或数据,通过连接线传递数据和触发执行。
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 触发器 │────▶│ 处理器 │────▶│ 输出 │
│ onClick │ │ 数据转换 │ │ 更新状态 │
└─────────┘ └─────────┘ └─────────┘节点类型
1. 触发器节点 (Trigger)
触发器节点是逻辑流的起点,响应特定事件。
| 节点 | 触发条件 | 输出数据 |
|---|---|---|
| onClick | 组件被点击 | event, target |
| onChange | 输入值改变 | value, event |
| onLoad | 页面/组件加载 | - |
| onSubmit | 表单提交 | formData |
| onTimer | 定时触发 | timestamp |
| onKeyPress | 键盘按键 | key, event |
┌──────────────────┐
│ 🎯 onClick │
├──────────────────┤
│ 目标: Button-1 │
├──────────────────┤
│ ●──▶ event │
│ ●──▶ target │
└──────────────────┘2. 操作节点 (Action)
操作节点执行具体的操作。
HTTP 请求
┌──────────────────────┐
│ 🌐 HTTP Request │
├──────────────────────┤
│ URL: /api/users │
│ Method: [▼ GET] │
│ Headers: {...} │
├──────────────────────┤
│ ▶──● url │
│ ▶──● body │
├──────────────────────┤
│ ●──▶ response │
│ ●──▶ error │
└──────────────────────┘状态更新
┌──────────────────────┐
│ 📝 Set State │
├──────────────────────┤
│ 目标: userList │
│ 操作: [▼ replace] │
├──────────────────────┤
│ ▶──● value │
├──────────────────────┤
│ ●──▶ done │
└──────────────────────┘页面跳转
┌──────────────────────┐
│ 🔗 Navigate │
├──────────────────────┤
│ 路径: /dashboard │
│ 参数: {id: ${id}} │
├──────────────────────┤
│ ▶──● params │
└──────────────────────┘3. 逻辑节点 (Logic)
逻辑节点用于控制流程和数据处理。
条件分支
┌──────────────────────┐
│ ❓ Condition │
├──────────────────────┤
│ 条件: value > 0 │
├──────────────────────┤
│ ▶──● input │
├──────────────────────┤
│ ●──▶ true │
│ ●──▶ false │
└──────────────────────┘循环
┌──────────────────────┐
│ 🔄 ForEach │
├──────────────────────┤
│ 变量名: item │
├──────────────────────┤
│ ▶──● array │
├──────────────────────┤
│ ●──▶ item │
│ ●──▶ index │
│ ●──▶ done │
└──────────────────────┘数据转换
┌──────────────────────┐
│ 🔧 Transform │
├──────────────────────┤
│ 表达式: │
│ data.map(x => x.name)│
├──────────────────────┤
│ ▶──● data │
├──────────────────────┤
│ ●──▶ result │
└──────────────────────┘4. 数据节点 (Data)
数据节点提供静态数据或变量引用。
┌──────────────────────┐
│ 📦 Variable │
├──────────────────────┤
│ 名称: userList │
├──────────────────────┤
│ ●──▶ value │
└──────────────────────┘
┌──────────────────────┐
│ 📄 Constant │
├──────────────────────┤
│ 类型: [▼ Object] │
│ 值: {"key": "value"} │
├──────────────────────┤
│ ●──▶ value │
└──────────────────────┘连接规则
端口类型
- 输入端口 (▶──●) - 接收数据,位于节点左侧
- 输出端口 (●──▶) - 发送数据,位于节点右侧
- 执行端口 - 控制执行顺序(箭头形状)
- 数据端口 - 传递数据(圆形)
数据类型
端口有不同的数据类型,通过颜色区分:
| 颜色 | 类型 | 示例 |
|---|---|---|
| 🟢 绿色 | String | "hello" |
| 🔵 蓝色 | Number | 42 |
| 🟡 黄色 | Boolean | true |
| 🟣 紫色 | Object | |
| 🔴 红色 | Array | [1, 2, 3] |
| ⚪ 白色 | Any | 任意类型 |
连接限制
- 输出端口可连接多个输入端口(一对多)
- 输入端口只能接收一个连接(多对一时自动断开旧连接)
- 类型不兼容的端口无法连接(除非目标是 Any 类型)
节点图编辑器界面
┌─────────────────────────────────────────────────────────────────┐
│ 节点图: click-handler.json [▶ 运行] [🐛 调试] [💾 保存] │
├──────────┬────────────────────────────────────────┬─────────────┤
│ │ │ │
│ 节点 │ │ 属性 │
│ 面板 │ 画布区域 │ 面板 │
│ │ │ │
│ ────────│ │─────────────│
│ │ │ │
│ 变量 │ │ 调试 │
│ 列表 │ │ 信息 │
│ │ │ │
└──────────┴────────────────────────────────────────┴─────────────┘操作指南
添加节点
- 从面板拖拽 - 从左侧节点面板拖拽到画布
- 右键菜单 - 在画布空白处右键,选择"添加节点"
- 快捷键 - 按
Tab打开快速添加菜单
连接节点
- 从输出端口拖拽到输入端口
- 松开鼠标完成连接
- 拖拽到空白处可快速创建匹配的新节点
编辑节点
- 双击 - 编辑节点名称或表达式
- 右键 - 打开节点菜单(复制、删除、断开连接等)
- 属性面板 - 在右侧面板编辑详细属性
画布操作
| 操作 | 方式 |
|---|---|
| 平移 | 中键拖拽 / Space + 左键拖拽 |
| 缩放 | 滚轮 / Ctrl + 滚轮 |
| 框选 | 左键拖拽(从空白处开始) |
| 全选 | Ctrl/Cmd + A |
调试功能
断点
在节点上设置断点,执行到该节点时暂停:
┌──────────────────┐
│ 🔴 Transform │ ← 红点表示断点
├──────────────────┤
│ ... │
└──────────────────┘单步执行
暂停时可以:
- 继续 (F5) - 继续执行直到下一个断点
- 单步 (F10) - 执行当前节点,暂停在下一个
- 进入 (F11) - 进入子图(如果有)
- 停止 (Shift + F5) - 停止调试
状态监控
调试面板显示:
┌─────────────────────────────┐
│ 📊 状态监控 │
├─────────────────────────────┤
│ 变量 │
│ ├─ userList: [...] │
│ ├─ loading: false │
│ └─ error: null │
│ │
│ 当前节点: Transform-1 │
│ 输入: {data: [...]} │
│ 输出: (等待执行) │
└─────────────────────────────┘执行日志
┌─────────────────────────────┐
│ 📋 执行日志 │
├─────────────────────────────┤
│ 10:23:45 onClick 触发 │
│ 10:23:45 HTTP GET /api/users│
│ 10:23:46 响应: 200 OK │
│ 10:23:46 Transform 执行 │
│ 10:23:46 SetState 完成 │
└─────────────────────────────┘实战示例
示例 1: 点击按钮加载数据
┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐
│onClick │────▶│SetState │────▶│HTTP GET │────▶│SetState │
│Button │ │loading=true │ │/api/users │ │userList │
└─────────┘ └─────────────┘ └─────────────┘ └───────────┘
│
▼
┌─────────────┐
│SetState │
│loading=false│
└─────────────┘示例 2: 表单验证和提交
┌─────────┐ ┌─────────────┐
│onSubmit │────▶│Validate │
│Form │ │formData │
└─────────┘ └─────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│✅ valid │ │❌ invalid │
│HTTP POST │ │ShowToast │
│/api/submit │ │"验证失败" │
└─────────────┘ └─────────────┘示例 3: 条件渲染
┌─────────┐ ┌─────────────┐
│Variable │────▶│Condition │
│isLoggedIn│ │value === true│
└─────────┘ └─────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌─────────────┐ ┌─────────────┐
│✅ true │ │❌ false │
│Show │ │Show │
│Dashboard │ │LoginForm │
└─────────────┘ └─────────────┘高级功能
子图 (Subgraph)
将常用逻辑封装为子图,实现复用:
┌─────────────────────────────┐
│ 📁 FetchAndCache │
├─────────────────────────────┤
│ 输入: │
│ ▶──● url │
│ ▶──● cacheKey │
├─────────────────────────────┤
│ 输出: │
│ ●──▶ data │
│ ●──▶ fromCache │
└─────────────────────────────┘自定义代码节点
当内置节点无法满足需求时,可以使用代码节点:
javascript
// 输入: data (Array)
// 输出: result
const result = data
.filter((item) => item.active)
.sort((a, b) => b.score - a.score)
.slice(0, 10);
return { result };异步处理
支持 Promise 和 async/await:
javascript
// 异步代码节点
const response = await fetch(url);
const data = await response.json();
return { data };最佳实践
1. 命名规范
为节点设置清晰的名称:
✅ "加载用户列表"
✅ "验证表单数据"
✅ "更新购物车状态"
❌ "Node-1"
❌ "Transform"
❌ "HTTP"2. 模块化
将复杂逻辑拆分为多个子图:
✅ 主图 → 用户认证子图 → 数据处理子图
❌ 一个图包含所有逻辑3. 错误处理
始终处理错误分支:
┌─────────┐
│HTTP GET │
└─────────┘
│
├──▶ success → 处理数据
│
└──▶ error → 显示错误提示4. 注释节点
使用注释节点说明复杂逻辑:
┌─────────────────────────────┐
│ 📝 注释 │
│ 这里处理用户权限验证 │
│ 只有管理员可以执行后续操作 │
└─────────────────────────────┘