X6 React 节点渲染实战使用 antv/x6-react-shape 构建、更新与桥接 React 组件【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6本文以 X6 官方教程《React Nodes》为核心系统讲解如何通过独立渲染包antv/x6-react-shape在 X6 图中使用 React 组件渲染节点、通过effect字段实现节点内容的高效更新以及借助Portal模式让节点组件访问应用级Context。读完本文你将能够在自己的 X6 项目中直接落地React 节点 数据驱动更新 外部状态桥接的完整方案。说明本文对应的官方英文教程原文位于 react.en.md文中的可运行示例代码可在仓库的 site/src/tutorial/intermediate/react 目录下找到完整源码。一、为什么需要 React 节点X6 本身使用 SVG 与 HTML 渲染节点内容见项目描述与 入门教程 中 X6 supports usingSVGandHTMLto render node content 的说明。在此基础上社区和官方还提供了antv/x6-react-shape这一独立渲染包允许直接使用React 组件来描述节点内容。使用 React 渲染节点的典型收益在官方快速入门文档中有明确场景例如给节点添加右键菜单用纯 SVG 实现会比较复杂而用 React 节点配合成熟的组件库如 Ant Design 的Dropdown可以轻松完成。仓库中的 react-shape 入门示例 正是这一场景的完整实现它注册了一个名为custom-react-node的 React 节点节点组件内直接使用Dropdown组件并绑定contextMenu触发事件再通过node.prop(label)读取节点 label 渲染文本。二、安装与版本兼容性antv/x6-react-shape是一个独立 npm 包需要与antv/x6一起安装。当前仓库的站点工程中将其声明为antv/x6-react-shape: ^3.x见 site/package.json对应 X6 3.x 主版本。官方文档给出了必须注意的版本兼容约束X6 3.x 必须搭配 x6-react-shape 3.x 使用x6-react-shape 自2.0.8起仅支持React 18 及以上若你的项目使用 React 低于 18请将 x6-react-shape 锁定到2.0.8并搭配 X62.x使用。因此在引入之前请先核对你的 React 版本与 X6 版本避免出现运行时兼容问题。三、渲染节点使用 register 注册 React 组件渲染 React 节点的核心 API 是antv/x6-react-shape导出的register函数。基本流程分三步定义 React 组件、注册 shape、将 shape 添加到图中。官方教程给出了最小示例import { register } from antv/x6-react-shape const NodeComponent () { return ( div classNamereact-node Progress typecircle percent{30} width{80} / /div ) } register({ shape: custom-basic-react-node, width: 100, height: 100, component: NodeComponent, }) graph.addNode({ shape: custom-basic-react-node, x: 60, y: 100, })其中register配置项的含义为shape注册的节点形状名称后续addNode/fromJSON时通过该名称引用width/height节点默认尺寸component用于渲染节点内容的 React 组件。示例完整代码位于 basic/index.tsx它演示了更贴近真实项目的用法组件内使用 Ant Design 的Progress圆形进度条作为节点内容注册后创建Graph实例设置画布背景色#F2F7FA通过graph.addNode({ shape: custom-basic-react-node, x: 60, y: 100 })添加节点最后调用graph.centerContent()将内容居中。可以看到React 组件被直接当作节点的视觉外壳节点的位置x/y仍由 X6 图模型管理而外观完全由 React 组件自由绘制这意味着你可以把任何 React 生态的组件进度条、表格、下拉菜单、图表等嵌入图中。四、更新节点effect 字段与数据驱动重渲染静态渲染往往不够业务中经常需要根据数据变化刷新节点内容。官方文档给出的机制与 X6 的 HTML 节点一脉相承HTML 节点文档同样介绍了effect机制见 html.en.md注册节点时提供effect字段它是节点props的数组当其中任一 prop 发生变化时对应的 React 组件会重新渲染。register({ shape: custom-update-react-node, width: 100, height: 100, effect: [data], component: NodeComponent, }) const node graph.addNode({ shape: custom-update-react-node, x: 60, y: 100, data: { progress: 30, }, }) setInterval(() { const { progress } node.getData{ progress: number }() node.setData({ progress: (progress 10) % 100, }) }, 1000)这里的关键链路是effect: [data]声明当dataprop 变化时触发重渲染addNode时传入初始dataprogress: 30定时器中通过node.getData()读取当前数据、node.setData()写入新数据从而驱动 React 组件重新渲染。完整示例见 update/index.tsx其节点组件接收node参数并读取数据const NodeComponent ({ node }: { node: Node }) { const { progress } node.getData() return ( div classNamereact-node Progress typecircle percent{progress} width{80} / /div ) }从源码结构可以看出节点组件会收到 X6 的Node实例作为 props因此组件内部既可以读data也可以通过node.prop(...)读取其他属性如 react-shape 入门示例 中用node.prop(label)读取 label。这一模式在仓库的其他示例中也被反复使用例如 examples/src/pages/react/index.tsx 中注册了algo-node-1节点effect: [data]组件通过node.getData()读取name字段渲染算法节点名称随后每秒node.setData({ name: ... })更新名称展示数据驱动刷新的效果。需要提醒的是effect数组应只声明真正需要触发重渲染的 prop 键避免无关数据变化引起不必要的组件刷新从而影响大图渲染性能。五、Portal 模式让节点组件访问应用级 Context默认情况下antv/x6-react-shape会把组件直接渲染到节点自身的 DOM 容器中其内部实现等价于import { createRoot, Root } from react-dom/client const root createRoot(container) // container 为节点容器 root.render(component)这种渲染方式有一个显著缺点组件不在常规的 React 组件树中因此无法访问应用外层的Context例如主题、国际化、数据仓库等。当节点组件确实需要消费这些外部状态时官方推荐使用Portal 模式。Portal 模式的用法是调用getProvider()获取一个X6ReactPortalProvider组件并将其挂载在提供Context的 Provider 之内import { register, getProvider } from antv/x6-react-shape const X6ReactPortalProvider getProvider() // 注意一个 graph 只能申明一个 portal provider const ProgressContext React.createContext(30) const NodeComponent () { const progress React.useContext(ProgressContext) return ( div classNamereact-node Progress typecircle percent{progress} width{80} / /div ) } register({ shape: custom-portal-react-node, width: 100, height: 100, component: NodeComponent, })渲染时把 Provider 与节点容器放在同一棵 React 树中render() { return ( div classNamereact-portal-app ProgressContext.Provider value{this.state.progress} X6ReactPortalProvider / /ProgressContext.Provider div classNameapp-btns Button onClick{this.changeProgress}Add/Button /div div classNameapp-content ref{this.refContainer} / /div ) }完整示例见 portal/index.tsx。它的运行逻辑是ProgressContext的 value 由 React 组件状态驱动点击 Add 按钮通过setState改变进度值由于节点组件是通过 Portal 挂在 Provider 之下的useContext能实时拿到最新值并重渲染无需走 X6 的setData链路。仓库的 examples/src/pages/react/portal.tsx 还提供了一个主题切换light/dark的 Portal 示例演示节点组件通过useContext消费ThemeContext切换样式。使用 Portal 模式时请注意官方注释中的约束一个 graph 只能申明一个 portal provider多个图需要分别管理各自的 Provider 实例。六、两种更新路径的选择建议结合官方文档与仓库示例React 节点的数据流动有两条路径可按场景选用更新方式触发机制适用场景effectnode.setData()X6 数据模型驱动prop 变化触发组件重渲染节点数据与图数据绑定需要随图模型持久化、序列化toJSON的业务数据Portal 外部ContextReact 自身状态驱动setState/useState触发重渲染需要消费应用级 Context主题、国际化、全局 store或状态由 React 树外部统一管理当节点数据需要参与graph.toJSON()导出如 入门教程 中介绍的序列化场景时优先选择effectdata方案让业务数据保留在 X6 节点模型中当节点仅需反映 React 树内部状态时Portal 方案更加自然。七、小结本文围绕 X6 官方《React Nodes》教程完整介绍了使用antv/x6-react-shape的三个核心能力渲染通过register({ shape, width, height, component })将 React 组件注册为节点形状随后即可在addNode/fromJSON中按 shape 名使用更新利用effect字段声明需要监听的 prop典型为data配合node.getData()/node.setData()实现数据驱动的组件重渲染桥接使用getProvider()获取 Portal Provider并将其置于应用 Context 之下让节点组件能够像普通 React 组件一样消费外部上下文。同时务必牢记版本约束X6 3.x 搭配 x6-react-shape 3.xx6-react-shape 2.0.8 起要求 React 18旧项目需锁定 2.0.8 并配合 X6 2.x。掌握这三项能力后你就可以在 X6 图中自由组合任意 React 生态组件构建出交互复杂、数据实时刷新的可视化应用。【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考