LogicFlow 实例注册 API 全解析:register 与 batchRegister 实现自定义节点与边
2026/9/15 11:43:19 网站建设 项目流程

LogicFlow 实例注册 API 全解析:register 与 batchRegister 实现自定义节点与边

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

本文以 LogicFlow 官方 API 文档《注册》为骨架,深入讲解 LogicFlow 实例方法registerbatchRegister的完整用法:从签名、参数类型、核心示例,到二者内部实现原理(viewMap / modelMap 注册表、observer包装、内置元素默认注册)逐一拆解。读完本文,你将掌握在 LogicFlow 中注册自定义节点/边的两种方式,并能结合源码理解注册失败时的报错链路,从容应对"找不到 XX 对应的节点"这类常见问题。

概述:注册机制在 LogicFlow 中的位置

LogicFlow 是一个专注于业务自定义的流程图编辑框架(见 README.md),支持脑图、ER 图、UML、工作流等多种图编辑场景。它的扩展能力建立在"注册(Register)"机制之上:任何自定义节点、自定义边,都必须先通过注册告诉实例"这个 type 长什么样(view)"以及"这个 type 有哪些数据行为(model)",之后才能在图数据中被引用、渲染和交互。

本页 API 文档位于 register.zh.md,隶属于"LogicFlow 实例"分组(order: 2),是官方 API 文档中关于实例级注册方法的唯一入口。它覆盖两个核心方法:

方法作用签名
register注册单个自定义节点或边register(config: RegisterConfig): void
batchRegister批量注册多个自定义节点或边batchRegister(configList: RegisterConfig[]): void

插件(Extension)的全局注册不在实例方法范畴内,而是通过 LogicFlow.use 完成,本文不展开。

register:注册单个自定义节点或边

register用于向当前 LogicFlow 实例注册一个自定义节点或边,是使用频率最高的扩展入口。

签名与参数

register(config: RegisterConfig): void

参数类型RegisterConfig的完整定义,见类型文档 MainTypes.zh.md。它包含以下属性:

属性名类型描述
typestring指定要注册的图元素类型,必填。它是后续addNodeaddEdgerender时引用该元素的唯一标识。
viewComponentType<any> & { isObserved?: boolean }与图元素关联的视图组件(React 组件)。可包含可选布尔值isObserved,指示该组件是否已被观察(mobx 响应式)。
modelGraphElementCtor定义图元素的模型构造函数,必填。应为BaseNodeModelCtor(节点模型)或BaseEdgeModelCtor(边模型),见 LogicFlow.tsx。
isObserverViewboolean (可选)指示视图是否为观察者视图。设为true表示视图会响应模型变化(默认行为);设为false可跳过observer包装。

官方示例:自定义矩形节点

文档给出的标准示例,是继承内置RectNode/RectNodeModel实现一个圆角矩形节点:

import { RectNode, RectNodeModel } from '@logicflow/core'; class CustomRectNode extends RectNode {} class CustomRectModel extends RectNodeModel { setAttributes() { this.width = 200; this.height = 80; this.radius = 50; } } lf.register({ type: 'custom-rect', view: CustomRectNode, model: CustomRectModel, });

拆解这段代码:

  • viewCustomRectNode继承自RectNode,不重写任何渲染逻辑,直接复用内置矩形的 SVG 渲染。
  • modelCustomRectModel继承自RectNodeModel,在setAttributes()生命周期钩子中重定义尺寸与圆角(宽 200、高 80、圆角半径 50)。setAttributes在模型初始化时被调用,是自定义节点最常见的覆写入口。
  • type'custom-rect'是自定义的标识,之后通过lf.addNode({ type: 'custom-rect', x: 100, y: 100 })即可实例化该节点。

注册边的方式完全一致,只需将view/model换成边对应的基类(如PolylineEdge/PolylineEdgeModel),并把type设为边类型。

官方示例:批量注册多个元素

当需要一次性注册多个自定义元素时,使用batchRegister

lf.batchRegister([ { type: 'user', view: UserNode, model: UserModel, }, { type: 'user1', view: UserNode1, model: UserModel1, }, ]);

它接受RegisterConfig[]数组,内部逐项执行与register相同的注册逻辑,适用于"一次引入、注册一整套业务元素"的场景。

源码解读:register 到底做了什么

只看用法难免知其然不知其所以然。下面结合 packages/core/src/LogicFlow.tsx 的实现,说明注册的内部链路。

注册的两种重载方式

register在源码中有两个重载(LogicFlow.tsx):

register(element: RegisterConfig): void register( type: string, fn: RegisterElementFunc, isObserverView?: boolean, ): void
  • 方式一(推荐):传入RegisterConfig对象,即文档示例的写法。
  • 方式二:传入type与一个RegisterElementFunc函数。源码注释明确标注该方式"不推荐,极个别在自定义的时候需要用到 lf 的情况下可以用这种方式",因为大多数场景可以直接在 view 中通过this.props获取graphModel,或在 model 中通过this.graphModel获取方法(LogicFlow.tsx)。

方式二的函数签名来自类型文档中的RegisterElementFuncRegisterParam(见 MainTypes.zh.md):

export type RegisterElementFunc = (params: RegisterParam) => RegisterElement export type RegisterParam = { h: typeof h; // hyperscript 函数,用于创建虚拟 DOM [key: string]: unknown; // 其它由框架注入的基类(RectNode、RectNodeModel 等)与用户自定义属性 }

执行方式二时,源码会构造一个registerParam对象,把内置的BaseNodeBaseEdgeModelRectNodeRectNodeModelPolylineEdgeBezierEdgeModelh以及当前type全部注入(LogicFlow.tsx),随后从函数返回值中解构出viewmodel完成注册。

registerElement:注册的核心实现

无论哪种方式,最终都会收敛到registerElement(LogicFlow.tsx):

private registerElement(config: RegisterConfig) { let ViewComp = config.view if (config.isObserverView !== false && !ViewComp.isObserved) { ViewComp.isObserved = true ViewComp = observer(ViewComp) } this.setView(config.type, ViewComp) this.graphModel.setModel(config.type, config.model) }

关键点:

  1. observer 包装:只要isObserverView不为false且视图尚未被包装(isObserved为假),就会用 mobx 的observer()把视图组件包一层,使其响应模型变化。这就是为什么文档中view类型上带有isObserved?: boolean标记。
  2. 视图注册表 viewMapsetViewtype → ViewComp存入this.viewMap(Map),供渲染层按类型查找视图。
  3. 模型注册表 modelMapthis.graphModel.setModel(type, config.model)type → ModelClass存入GraphModelmodelMap(见 GraphModel.ts),供数据层按类型实例化模型。

内置元素的默认注册

实际上,实例初始化时就已经通过batchRegister注册了一批内置元素。defaultRegister中定义并注册了 11 个默认类型(LogicFlow.tsx):

  • 节点rectcirclepolygontextellipsediamondhtml
  • linepolylinebezier
private defaultRegister() { const defaultElements: RegisterConfig[] = [ { type: 'rect', view: _View.RectNode, model: _Model.RectNodeModel }, { type: 'circle', view: _View.CircleNode, model: _Model.CircleNodeModel }, // ... polyline / bezier 等 ] this.batchRegister(defaultElements) }

这解释了为什么直接使用type: 'rect'无需任何注册——它早已随实例初始化注册完毕。同时这也是batchRegister的第一个真实使用者,可见"批量注册"本就是框架内部的常规操作。

注册与消费:一次完整的闭环

注册不是终点,注册表最终服务于数据渲染。在 GraphModel.ts 中,getModel(type)负责从modelMap按类型取出模型构造函数:

getModel(type: string) { return this.modelMap.get(type) }

渲染数据转换为模型时,会先查注册表,查不到即抛出错误。例如节点转换(GraphModel.ts):

const Model = this.getModel(node.type) as BaseNodeModelCtor if (!Model) { throw new Error( `找不到${node.type}对应的节点,请确认是否已注册此类型节点。`, ) }

边转换同理(GraphModel.ts):

const Model = this.getModel(type) as BaseEdgeModelCtor if (!Model) { throw new Error(`找不到${type}对应的边。`) }

这两处正是新手最常遇到报错的根源:图数据中出现了未注册的 type。排查方法很直接——检查register/batchRegister是否覆盖了数据中的所有type

由此可以得到一个清晰的注册消费闭环:

lf.register({ type, view, model }) │ ▼ viewMap(type → 视图组件) ──► 渲染阶段:getView(type) 渲染 modelMap(type → 模型类) ──► 数据阶段:getModel(type) 实例化模型 │ type 未注册则抛出 "找不到 XX 对应的节点/边"

实践建议与注意事项

结合文档与源码,总结以下实战要点:

  1. type 全局唯一type既是注册表键,也是图数据中的引用标识。重复注册同名 type 会覆盖之前的注册,跨实例注册互不影响(注册表挂在具体实例的 viewMap / modelMap 上)。
  2. 优先对象式注册register(config)的写法清晰直观,是推荐用法;函数式重载仅在确需访问lf场景才使用(源码注释明确标注"不推荐")。
  3. 默认 isObserverView 为 true:若自定义视图内部自行处理了响应式(例如使用外部状态),可通过isObserverView: false跳过 observer 包装以省去无谓渲染开销。
  4. 依赖内置基类:自定义节点/边应继承@logicflow/core导出的基类(RectNodePolylineEdge、对应 Model 等),而不是从零实现,这样能复用渲染、选中、连线等成熟能力。
  5. 批处理用 batchRegister:元素较多时用batchRegister一次注册,语义更清晰;框架自身的内置注册也是这么做的。
  6. 排查"找不到"报错:遇到找不到${type}对应的节点/边,优先核对:该 type 是否已注册?注册的 type 字符串是否与图数据中的 type 完全一致(注意大小写与空格)?

关联文档索引

  • 本文依据的 API 文档:register.zh.md
  • 参数类型定义:MainTypes.zh.md(含RegisterConfigRegisterElementFuncRegisterParamBaseNodeModelCtorBaseEdgeModelCtor
  • 核心实现:LogicFlow.tsx(register/registerElement/batchRegister/defaultRegister)、GraphModel.ts(getModel/setModel
  • 插件注册方式:use.zh.md
  • 更多实战注册示例,可参考教程目录中的扩展类文档(如 group.zh.md、dynamic-group.zh.md)以及 examples/feature-examples/src/components/nodes 下的自定义节点示例源码。

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

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

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

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

立即咨询