LogicFlow 渲染与数据:render、getGraphData 与 adapterIn/adapterOut 数据适配器全解析
2026/9/15 16:23:53 网站建设 项目流程

LogicFlow 渲染与数据:render、getGraphData 与 adapterIn/adapterOut 数据适配器全解析

【免费下载链接】LogicFlowA flow chart editing framework focus on business customization. 专注于业务自定义的流程图编辑框架,支持实现脑图、ER图、UML、工作流等各种图编辑场景。项目地址: https://gitcode.com/GitHub_Trending/lo/LogicFlow

本指南聚焦 LogicFlow 实例层的渲染入口与图数据读写能力,围绕renderrenderRawDatagetGraphDatagetGraphRawDataclearData五个核心方法,以及adapterIn/adapterOut两个数据适配器接口,讲解如何在接入业务系统时完成"业务数据 → LogicFlow 标准数据"的双向转换。读完本文,你将掌握 LogicFlow 图数据的渲染时机、读取方式、清空策略,以及如何用适配器无缝对接任意第三方流程数据格式。

数据读写全景:谁负责渲染,谁负责导出

在 LogicFlow.tsx 中,实例的渲染与数据读取能力由一组对称的方法构成,它们围绕两个概念展开:

  • LogicFlow 原生数据(Raw Data):即GraphData,由nodesedges数组组成,是画布内部模型(Model)直接使用的数据结构。
  • 业务数据(Biz Data):接入方系统自身定义的流程数据格式,例如 BPMN XML、自研审批流 JSON 等。

四组核心 API 的对应关系如下:

操作方向经过适配器不经过适配器
写入(渲染)render(graphData)renderRawData(graphData)
读取(导出)getGraphData(...params)getGraphRawData()
清空clearData()(内部强制触发一次空渲染)

render:渲染入口与 adapterIn 转换

签名与行为

render(graphData: unknown): void

render是渲染图数据的标准入口。当实例配置了adapterIn时,传入的数据会先经过adapterIn转换为 LogicFlow 原生数据,再渲染;未配置时则直接按 LogicFlow 标准格式渲染。

参数说明

名称类型必传说明
graphDataunknown图数据,格式取决于是否配置了adapterIn。未配置时需符合 LogicFlow 标准格式;已配置时可以是任意业务数据结构。

基础示例:直接渲染标准格式

lf.render({ nodes: [{ id: 'node_1', type: 'rect', x: 120, y: 100 }], edges: [], });

底层实现链路

从源码看,render的实现非常清晰(LogicFlow.tsx):

render(graphData: GraphConfigData) { let graphRawData = cloneDeep(graphData) if (this.adapterIn) { graphRawData = this.adapterIn(graphRawData) } this.renderRawData(graphRawData) }

有两个细节值得注意:

  1. 数据先做深拷贝render首先对传入数据执行cloneDeep,避免外部对象被内部模型直接引用而相互污染。尤其当接入 Vue 这类对数据做响应式代理(Observe)的框架时,这一步至关重要——formatData工具(compatible.ts)通过JSON.parse(JSON.stringify(data))将带代理的对象转为纯对象,注释中特别说明该实现是"对数据实现兼容处理"。
  2. 委托给renderRawDatarender本身不直接操作画布,而是把转换后的数据交给renderRawData统一处理,保证"带适配器渲染"与"原生渲染"最终走同一条渲染管线。

renderRawData:跳过适配器的原生渲染

renderRawData(graphData: GraphData): void

renderRawData直接渲染 LogicFlow 原生图数据,不经过adapterIn转换。当你手里的数据已经是标准GraphData结构时,应优先使用它,避免被适配器二次转换。

参数说明

名称类型必传说明
graphDataGraphDataLogicFlow 原生图数据。

示例

lf.renderRawData({ nodes: [{ id: 'node_1', type: 'rect', x: 120, y: 100 }], edges: [], });

渲染管线的关键环节

renderRawData是真正触及画布模型的方法(LogicFlow.tsx),其调用链为:

  1. graphDataToModel:将图数据转换为内部 Model。在 GraphModel.ts 中,该方法会先清空已有的elementsModelMapnodeModelMapedgeModelMap,再根据graphData.nodes通过getModelAfterSnapToGrid生成节点模型、根据graphData.edges通过getModel(edge.type ?? currEdgeType)生成边模型;若边类型未注册会直接抛错找不到${edge.type}对应的边。
  2. 历史记录监听:当options.history !== false时,调用history.watch(this.graphModel),使渲染后的操作进入撤销/重做栈。
  3. Preact 渲染<Graph>组件:将图模型注入视图层完成绘制。
  4. 触发GRAPH_RENDERED事件:渲染完成后 emitEventType.GRAPH_RENDERED,事件负载中包含data(当前图数据)与graphModel,供插件与业务方监听渲染完成时机。

getGraphData:读取图数据与 adapterOut 转换

签名与行为

getGraphData(...params: any[]): GraphConfigData | unknown

获取当前图数据。当配置了adapterOut时,返回值会先经过适配器转换为业务数据;未配置时返回 LogicFlow 标准格式的GraphConfigData

参数说明

名称类型必传说明
...paramsany[]透传给adapterOut的额外参数。

返回值

  • 未配置adapterOut:返回GraphConfigData
  • 已配置adapterOut:返回适配后的业务数据(unknown)。

示例

// 未配置 adapterOut 时,params 无实际作用 const data = lf.getGraphData(['property1', 'property2']);

底层实现:params 的透传机制

源码实现(LogicFlow.tsx):

getGraphData(...params: any): GraphData | unknown { const data = this.getGraphRawData() if (this.adapterOut) { return this.adapterOut(data, ...params) } return data }

getGraphData始终先通过getGraphRawData()拿到当前原生数据,再决定是否交给adapterOut处理;...params会被原样展开透传给adapterOut,这正是官方示例中通过getGraphData(['property1', 'property2'])向适配器传递"需要保留的字段列表"等业务参数的实现基础。

GraphConfigData 与 GraphData 的区别

  • GraphConfigData(MainTypes.zh.md):渲染入口使用的数据,nodesNodeConfig[] | undefinededgesEdgeConfig[] | undefined
  • GraphData(MainTypes.zh.md):导出时的数据类型,nodesNodeData[]edgesEdgeData[],两者都包含完整的节点/边配置信息。

getGraphRawData:不受适配器影响的原生导出

getGraphRawData(): GraphData

获取当前图的 LogicFlow 原生数据,不受adapterOut影响。无论实例是否配置了输出适配器,返回值始终是标准GraphData结构。

返回值

  • GraphData:由nodesedges两个数组构成的标准图数据。

示例

const rawData = lf.getGraphRawData(); console.log(rawData.nodes, rawData.edges);

实现与使用建议

源码仅一行(LogicFlow.tsx):

getGraphRawData(): GraphData { return this.graphModel.modelToGraphData() }

modelToGraphData(GraphModel.ts)遍历画布上的边与节点,调用各自的getData()收集数据,并自动过滤掉virtual(虚拟)边。官方源码注释对此有明确建议:

注意:getGraphData返回的数据受到 adapter 影响,所以其数据格式不一定是 LogicFlow 内部图数据格式。如果实现通用插件,请使用getGraphRawData

这意味着通用插件、历史快照、复制粘贴等需要"标准格式"场景一律应使用getGraphRawData,而面向具体业务方(如保存到后端)才使用getGraphData

clearData:清空画布

clearData(): void

清空当前画布中的全部节点和边数据。

示例

lf.clearData();

底层实现:为何要"强制刷新"

源码实现(LogicFlow.tsx):

clearData() { this.graphModel.clearData() // 强制刷新数据, 让 preact 清除对已删除节点的引用 this.render({}) }

这里有两个关键步骤:

  1. graphModel.clearData()(GraphModel.ts)清空模型层维护的节点与边;
  2. 随后调用render({})强制触发一次空渲染——注释明确指出,这是为了让Preact 清除对已删除节点的引用,防止 DOM 层残留对旧元素的引用。

因此在清理后,画布会恢复为空白状态,且渲染管线(含GRAPH_RENDERED事件)会再次走通,便于业务方统一监听。

adapterIn:输入数据适配器

adapterIn?: (data: unknown) => GraphData

自定义输入数据适配函数,用于在render前把业务数据转换为 LogicFlow 原生数据。只要在实例上赋值了该函数,之后每次调用render传入的数据都会被它先转换一次。

返回值

  • GraphData:转换后的标准图数据。

示例

lf.adapterIn = (bizData) => { // 将业务结构转换成 nodes / edges return { nodes: [], edges: [], }; };

声明位置与设计意图

adapterInadapterOut是定义在 LogicFlow 实例类上的可选实例属性(LogicFlow.tsx),类注释中写明了其设计初衷:

自定义数据转换方法。当接入系统格式和 LogicFlow 数据格式不一致时,可自定义此方法来进行数据格式转换。

也就是说,adapterIn面向的是"系统数据 → LogicFlow 标准数据"这一转换方向。常见的实战场景包括:

  • 将后端存储的 JSON 审批流结构映射为nodes/edges
  • 将 BPMN XML 解析后的对象树转换为 LogicFlow 节点与连线。

注意:adapterIn实例属性而非构造参数,需要在创建实例后、调用render前赋值;若要构建可复用的数据格式接入能力,可结合 bpmn-adapter 这类官方扩展了解更完整的适配实现。

adapterOut:输出数据适配器

adapterOut?: (data: GraphConfigData, ...params: any[]) => unknown

自定义输出数据适配函数,用于在getGraphData时把 LogicFlow 原生数据转换为业务数据。

参数说明

名称类型必传说明
dataGraphConfigData当前图数据。
...paramsany[]来自getGraphData(...params)的透传参数。

示例

lf.adapterOut = (data, reserveFields = []) => { return { processNodes: data.nodes, processEdges: data.edges, reserveFields, }; };

典型用法:业务字段透传

...params的存在让输出适配器具备了极大的灵活性。典型场景是:业务方在保存流程图时需要附带额外字段,此时可以通过getGraphData将字段列表透传进adapterOut,适配器再把这些字段并入返回结果:

// 保存时获取带业务字段的流程数据 const bizData = lf.getGraphData(['owner', 'version']);

结合源码实现可以看出,adapterOut的参数data实际来自getGraphRawData()的返回值,因此业务方拿到的永远是"当前画布的最新数据",无需关心内部 Model 的维护细节。

四个核心方法与适配器组合使用示例

将上述 API 组合起来,即可实现一个完整的"业务数据渲染 → 编辑 → 业务数据导出"闭环:

import LogicFlow from '@logicflow/core'; // 1. 定义输入适配器:后端 JSON → LogicFlow 标准数据 lf.adapterIn = (bizData) => { return { nodes: bizData.processNodes.map((n) => ({ id: n.id, type: n.nodeType, x: n.x, y: n.y, text: n.label, properties: n.props, })), edges: bizData.processEdges.map((e) => ({ sourceNodeId: e.from, targetNodeId: e.to, type: e.edgeType || 'polyline', })), }; }; // 2. 定义输出适配器:LogicFlow 标准数据 → 后端 JSON lf.adapterOut = (data, reserveFields = []) => ({ processNodes: data.nodes, processEdges: data.edges, reserveFields, }); // 3. 渲染业务数据(自动经过 adapterIn) lf.render(backendBizData); // 4. 读取原生数据(跳过适配器,适合通用逻辑) const raw = lf.getGraphRawData(); // 5. 读取业务数据(自动经过 adapterOut,可透传字段) const saveData = lf.getGraphData(['owner']); // 6. 清空画布 lf.clearData();

小结

  • 渲染入口render支持 adapterIn 转换后渲染,renderRawData直通原生数据;两者最终都汇聚到同一条graphDataToModel → Preact 渲染 → GRAPH_RENDERED管线。
  • 数据读取getGraphData可透传参数给adapterOut,适合业务导出;getGraphRawData返回标准GraphData,适合插件与通用逻辑。
  • 适配器adapterIn/adapterOut是定义在实例上的可选函数属性,方向相反、职责对称,是 LogicFlow 与任意业务数据格式对接的关键扩展点。
  • 清空clearData在清理模型后还会强制执行一次空渲染,以确保视图层引用被正确回收。

相关参考文档:MainTypes.zh.md 类型说明、核心实现 LogicFlow.tsx、GraphModel.ts。

【免费下载链接】LogicFlowA flow chart editing framework focus on business customization. 专注于业务自定义的流程图编辑框架,支持实现脑图、ER图、UML、工作流等各种图编辑场景。项目地址: https://gitcode.com/GitHub_Trending/lo/LogicFlow

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询