Reflex Flow 节点(Nodes)完全指南:从内置类型到自定义节点 📅 发布时间:2026/9/11 13:17:46 👁 浏览次数: Reflex Flow 节点Nodes完全指南从内置类型到自定义节点【免费下载链接】reflex️ Web apps in pure Python 项目地址: https://gitcode.com/GitHub_Trending/re/reflex导读本文基于 Reflex 仓库中 docs/enterprise/react_flow/nodes.md 展开系统讲解 Reflex Flow基于 React Flow 的纯 Python 流程图组件中节点的定义方式、内置类型、定位与样式配置以及如何编写自定义节点。读完本文你将掌握用字典声明Node的完整字段语义、input/default/output三种内置节点的适用场景、通过node_types注册自定义节点的完整流程以及受控/非受控数据流下节点状态同步的正确写法。节点流程图的基本构件在 overview.md 中流程图被定义为由节点Nodes通过边Edges连接而成的交互式图。节点是流程图的基本构建单元——每一个步骤、判断、数据源或出口都对应一个节点。框架本身只提供少量默认节点类型真正的能力来自自定义你可以让节点包含交互元素、展示动态数据、支持多个连接点。正如官方定位所说The framework provides the foundation—you provide the functionality and style框架提供地基你提供功能与样式。节点在画布上的连接点称为handle手柄通常位于节点的上、下、左、右侧边Edge就挂在 handle 上用户从某个 source handle 拖拽到某个 target handle 的过程会产生一条临时的connection line连接线。节点的位置坐标、视口的缩放与平移共同构成viewport视口这些概念与节点配置息息相关。Node 类型一个 Python 字典在 Reflex Flow 中节点被表示为普通的 Python 字典其类型Node可以从reflex_enterprise.components.flow.types导入。一个节点支持以下字段字段类型说明idstr节点的唯一标识符positiondict节点位置包含x、y坐标datadict传递给节点组件的任意数据typestr节点类型在node_types中定义sourcePositionstr源 handle 的位置可选top、right、bottom、lefttargetPositionstr目标 handle 的位置可选top、right、bottom、lefthiddenbool节点是否在画布上可见selectedbool节点当前是否被选中draggablebool节点是否可拖拽selectablebool节点是否可被选中connectablebool节点是否可与其他节点连接deletablebool节点是否可被删除widthfloat节点的宽度heightfloat节点的高度parentIdstr父节点 ID用于创建子流程sub-flowsstyledict节点的自定义样式classNamestr节点的 CSS 类名值得注意的是这些字段全部可选——React Flow 会为未提供的字段填充默认值。例如下面这个最小的节点声明仅提供id、type、position和data四个字段即可正常工作node { id: minimal-node, type: default, position: {x: 0, y: 0}, data: {label: Hello}, }字段背后的行为语义data是节点组件渲染的数据来源。内置节点会把data[label]渲染为节点标题自定义节点则可以自由读取data中的任意键例如自定义颜色选择器节点读取data[color]。draggable/selectable/connectable/deletable四个布尔字段构成节点的交互权限开关可以按节点单独覆盖适合做只读节点不可删除的起点/终点等业务约束。parentId配合父节点的position实现子节点相对父节点定位是构建分组节点与子流程的关键字段。sourcePosition/targetPosition控制 handle 出现在节点的哪一侧直接影响连线走向与视觉可读性下文Handle 定位一节会给出示例。内置节点类型input、default、outputReflex Flow 内置了三种开箱即用的节点类型覆盖最常见的入口—处理—出口三段式流程nodes: list[Node] [ { id: 1, type: input, position: {x: 100, y: 100}, data: {label: Start}, }, { id: 2, type: default, position: {x: 300, y: 100}, data: {label: Process}, }, { id: 3, type: output, position: {x: 500, y: 100}, data: {label: End}, }, ]三种类型的差异在于handle 的组合方式input—— 流程入口点只带 source handle只能作为边的起点向外出线default—— 标准节点同时带 source 和 target handle既能接收连线也能发出连线是最通用的节点类型output—— 流程出口点只带 target handle只能接收连线作为终点。在 basic_flow.md 的示例中正是用这三种节点搭出了输入节点 → 默认节点 → 输出节点的经典骨架并通过两条边其中一条animated: True将它们连接起来。这也是快速验证节点配置是否正确的起点先跑通内置类型再替换为自定义节点。基础节点配置节点定位Positioningposition是一个{x: ..., y: ...}字典表示节点左上角在画布坐标系中的坐标。坐标是相对视口坐标系的当用户平移或缩放视口时坐标会随之变化见 overview.md 中关于 viewport 的说明node { id: positioned-node, type: default, position: {x: 250, y: 150}, data: {label: Positioned Node}, }实际项目中节点定位还可以与snap_to_grid/snap_grid配合实现吸附网格与fit_viewTrue配合让整个图自适应视口。例如 nodes.md 自定义节点示例中设置了snap_grid(20, 20)和snap_to_gridTrue拖拽节点时会自动吸附到 20px 的网格上。节点样式Styling通过style字段可以传入任意 CSS 属性React Flow 使用内联样式渲染节点因此键名遵循驼峰命名法如borderRadius、backgroundColorstyled_node { id: styled-node, type: default, position: {x: 100, y: 200}, data: {label: Custom Style}, style: { background: #ff6b6b, color: white, border: 2px solid #ff5252, borderRadius: 8px, padding: 10px, }, }样式也可以与 Reflex 的响应式能力结合。注意在多个示例basic_flow.md、edges.md中节点样式统一写成node_style {color: #000000}这样的共享字典便于批量维护。Handle 定位sourcePosition与targetPosition控制 source/target handle 挂载在节点的哪一侧node_with_handles { id: handle-node, type: default, position: {x: 300, y: 300}, data: {label: Custom Handles}, sourcePosition: right, targetPosition: left, }上面的配置使该节点的边从右侧出、从左侧入形成自左向右的阅读流向。在 nodes.md 的自定义节点示例中输入节点设置sourcePosition: right、输出节点设置targetPosition: left配合fit_viewTrue自动缩放实现了一条横向展开的流程图。需要更精细控制时还可以在自定义节点中用rxe.flow.handle组件逐个声明 handle 的位置见下文自定义节点示例。自定义节点从 React 组件到node_types自定义节点是 Reflex Flow 的核心能力。官方文档强调创建自定义节点就像构建一个普通 React 组件一样简单——自定义节点本质上就是标准 React 组件因此可以展示任意内容、实现任意功能并且能拿到一系列 props 来扩展和定制默认行为。流程分三步用rx.memo编写一个接收节点数据 props 的组件函数在rxe.flow的node_types{自定义类型名: 组件函数}中注册在节点的type字段中引用该自定义类型名。下面完整复现文档中的颜色选择器节点示例该示例同时用到了边与rxe.flow.util工具函数可对照 utils.md 阅读from typing import Any import reflex as rx import reflex_enterprise as rxe from reflex_enterprise.components.flow.types import Connection, Edge, Node class CustomNodeState(rx.State): bg_color: rx.Field[str] rx.field(default#c9f1dd) nodes: rx.Field[list[Node]] rx.field( default_factorylambda: [ { id: 1, type: input, data: {label: An input node}, position: {x: 0, y: 50}, sourcePosition: right, style: {color: #000000}, }, { id: 2, type: selectorNode, data: {color: #c9f1dd}, position: {x: 300, y: 50}, }, { id: 3, type: output, data: {label: Output A}, position: {x: 650, y: 25}, targetPosition: left, style: {color: #000000}, }, { id: 4, type: output, data: {label: Output B}, position: {x: 650, y: 100}, targetPosition: left, style: {color: #000000}, }, ] ) edges: rx.Field[list[Edge]] rx.field( default_factorylambda: [ {id: e1-2, source: 1, target: 2, animated: True}, {id: e2a-3, source: 2, target: 3, animated: True}, {id: e2b-4, source: 2, target: 4, animated: True}, ] ) rx.event def on_change_color(self, color: str): self.nodes [ node if node[id] ! 2 or data not in node else {**node, data: {**node[data], color: color}} for node in self.nodes ] self.bg_color color rx.event def set_nodes(self, nodes: list[Node]): self.nodes nodes rx.event def set_edges(self, edges: list[Edge]): self.edges edges rx.memo def color_selector_node( data: rx.Var[dict], isConnectable: rx.Var[bool] ) - rx.Component: data data.to(dict) return rx.el.div( rxe.flow.handle( typetarget, positionleft, is_connectableisConnectable, ), rx.el.div( Custom Color Picker Node: , rx.el.strong(data[color]), ), rx.el.input( class_namenodrag, typecolor, on_changeCustomNodeState.on_change_color, default_valuedata[color], ), rxe.flow.handle( typesource, positionright, is_connectableisConnectable, ), class_nameborder border-1 p-2 rounded-sm, border_colorrx.color_mode_cond(black, ), colorblack, bgwhite, ) def node_stroke_color(node: rx.vars.ObjectVar[Node]): return rx.match( node[type], (input, #0041d0), (selectorNode, CustomNodeState.bg_color), (output, #ff0072), None, ) def node_color(node: rx.vars.ObjectVar[Node]): return rx.match( node[type], (selectorNode, CustomNodeState.bg_color), #fff, ) def custom_node(): return rx.box( rxe.flow( rxe.flow.background(bg_colorCustomNodeState.bg_color), rxe.flow.mini_map( node_stroke_colorrx.vars.function.ArgsFunctionOperation.create( (node,), node_stroke_color(rx.Var(node).to(Node)) ), node_colorrx.vars.function.ArgsFunctionOperation.create( (node,), node_color(rx.Var(node).to(Node)) ), ), rxe.flow.controls(), default_nodesCustomNodeState.nodes, default_edgesCustomNodeState.edges, nodesCustomNodeState.nodes, edgesCustomNodeState.edges, on_nodes_changelambda changes: CustomNodeState.set_nodes( rxe.flow.util.apply_node_changes(CustomNodeState.nodes, changes) ), on_edges_changelambda changes: CustomNodeState.set_edges( rxe.flow.util.apply_edge_changes(CustomNodeState.edges, changes) ), on_connectlambda connection: CustomNodeState.set_edges( rxe.flow.util.add_edge( connection.to(dict).merge({animated: True}).to(Connection), CustomNodeState.edges, ) ), node_types{selectorNode: color_selector_node}, color_modelight, snap_grid(20, 20), default_viewport{x: 0, y: 0, zoom: 1.5}, snap_to_gridTrue, attribution_positionbottom-left, fit_viewTrue, ), height100vh, width100vw, )这个示例集中展示了自定义节点的几个关键技术点rx.memo与 props 注入组件函数接收data节点数据字典与isConnectable节点是否可连接等 props。React Flow 会向自定义节点组件注入一整套标准 props这让你能够完全掌控渲染逻辑。手动声明 handle通过rxe.flow.handle(typetarget, positionleft, is_connectableisConnectable)与rxe.flow.handle(typesource, positionright, ...)在组件内精确放置连接点替代了节点级sourcePosition/targetPosition的粗粒度控制。这也印证了 overview.md 中节点可以拥有多个 handle支持复杂连接布局的说法。nodrag类名输入框的class_namenodrag让颜色选择器在拖拽画布时不被节点拖拽事件拦截这是自定义交互控件的常见坑。状态联动on_change_color事件在更新data[color]的同时更新bg_color并通过rx.match让 mini-map 中不同节点类型呈现不同的描边/填充色——节点状态的变化实时反映到画布与缩略图上。在rxe.flow中注册自定义节点自定义节点通过node_types字典注册见 components.md 中rxe.flow的 props 列表node_types: Mapping[str, Any]接受类型名 → 组件函数的映射。上面示例中node_types{selectorNode: color_selector_node}注册后任意type: selectorNode的节点都会用该组件渲染。同理自定义边通过edge_types注册参考 edges.md 的按钮边示例。节点状态管理受控与不受控流程在 interactivity.md 中文档对节点数据流给出了明确规范这直接决定你该如何组织节点状态受控controlled流程同时传入nodes与edges你的 Reflex State 是画布的唯一事实来源。此时必须将on_nodes_change与on_edges_change接到状态更新上否则用户拖拽、选中、删除节点的操作会被丢弃rxe.flow( nodesFlowState.nodes, edgesFlowState.edges, on_nodes_changelambda changes: FlowState.set_nodes( rxe.flow.util.apply_node_changes(FlowState.nodes, changes) ), on_edges_changelambda changes: FlowState.set_edges( rxe.flow.util.apply_edge_changes(FlowState.edges, changes) ), on_connectlambda connection: FlowState.set_edges( rxe.flow.util.add_edge(connection, FlowState.edges) ), fit_viewTrue, )不受控uncontrolled流程只传default_nodes与default_edges组件内部自行管理变更但你的 State 永远感知不到这些变更。适合静态展示或一次性初始化的场景。变更应用的位置约束文档特别强调了一个容易踩坑的约束rxe.flow.util.apply_node_changes/apply_edge_changes必须用在组件代码中即on_nodes_change/on_edges_change的回调 lambda 里绝不能在 State 的rx.event处理器内部调用。原因在于这些工具函数在客户端求值并产出更新后的列表然后才交给一个普通的 setter 事件处理器存储。换句话说组件端负责算State 端只负责存。事件触发时机参考 interactivity.mdon_nodes_change节点被拖拽、选中、缩放或删除时触发on_edges_change边被选中或删除时触发on_connect用户从一个 handle 拖拽到另一个 handle 完成连接时触发配合rxe.flow.util.add_edge构建新边列表。容器尺寸的必要性所有示例都在外层包了rx.box(..., height100vh, width100vw)之类的容器。文档明确警告flow 会填满父容器若不显式设置容器的高宽流程图将不可见。这是初学时最容易忽略的一行配置。进阶用 Flow API 钩子操作节点除了通过事件回调被动同步状态rxe.flow.api模块还提供了一组封装自 React FlowuseReactFlow的钩子见 hooks.md可用于主动读取和修改节点。节点相关的钩子包括get_nodes()返回流程中的所有节点set_nodes(nodes)设置流程中的节点add_nodes(nodes)向流程添加节点get_node(id)按 ID 返回节点update_node(id, node_update, replaceFalse)更新某个节点update_node_data(id, data_update, replaceFalse)更新节点的data这些钩子依赖流程被rxe.flow.provider包裹见 components.md 中FlowProvider的说明。结合 examples.md 的在连线拖放处添加节点示例可以组合出用户把连线拖到空白画布 → 通过rxe.flow.api.screen_to_flow_position把屏幕像素坐标换算成画布坐标 → 在落点动态插入新节点并连线的完整交互闭环——这正是把静态节点定义升级为动态节点操作的关键一步。小结Reflex Flow 的节点体系可以概括为三个层次声明层用字典按Node字段定义节点——id、position、data、type是最小必需sourcePosition/targetPosition控制 handle 方位style/className控制外观draggable/selectable/connectable/deletable/hidden/selected控制交互状态parentId支撑子流程内置层input只出、default可出可入、output只入三种类型满足标准流程骨架自定义层用rx.memo编写组件、在node_types注册、配合rxe.flow.handle精确定位连接点即可获得与 React 生态同级的节点定制能力。节点状态则遵循受控流程 组件端应用变更的规范rxe.flow.util.apply_node_changes在客户端完成变更合并State 端只负责存储结果。掌握这套节点模型后再阅读仓库内 components.mdrxe.flow的全部 props、utils.md节点/边的工具函数与 examples.md动态添加节点等完整示例即可构建出完整的交互式流程图应用。【免费下载链接】reflex️ Web apps in pure Python 项目地址: https://gitcode.com/GitHub_Trending/re/reflex创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考