ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

X6 React 节点渲染实战:基于 @antv/x6-react-shape 的组件化节点开发

X6 React 节点渲染实战:基于 @antv/x6-react-shape 的组件化节点开发 X6 React 节点渲染实战基于 antv/x6-react-shape 的组件化节点开发【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6本篇技术指南围绕 X6 图编辑引擎的 React 节点能力展开讲解如何使用antv/x6-react-shape独立包以 React 组件的方式渲染与更新节点内容并解决外部 Context 访问难题的 Portal 渲染模式。读完本文你将掌握register注册、effect响应式更新、getProviderPortal 接入的完整链路可直接将 Ant Design 等组件库集成进 X6 节点中。为什么需要 React 节点X6 本身是一个基于 SVG 与 HTML 渲染的图编辑库见项目根目录 README.md 对项目能力的描述原生节点内容由attrs与 SVG 标记驱动。但对于右键菜单、下拉框、进度条这类复杂交互内容直接用 SVG 拼装成本高、维护难。X6 生态为此提供了独立的 React 渲染包antv/x6-react-shape让你把节点内容当作普通 React 组件来写组件库开箱即用。从实现原理上看React 节点建立在 X6 核心的 HTML 节点机制之上核心库在 src/shape/html.ts 中为html节点定义了包含body矩形、foforeignObject与label文本的 markupReact 组件最终被渲染进foContent容器中。这也是为什么下面要讲的effect更新机制与核心 HTML 节点完全同源。版本兼容关系使用前务必确认版本匹配官方教程site/docs/tutorial/intermediate/react.zh.md明确给出如下约束X6 3.x 必须搭配x6-react-shape3.x 使用x6-react-shape自 2.0.8 起仅支持 React 18 及以上版本若项目使用 React 18 以下的版本请将x6-react-shape锁定到 2.0.8并使用 X6 2.x。本文示例站点site/package.json的依赖组合为antv/x6: workspace:*、antv/x6-react-shape: ^3.x、react: ^19.1.0正是文档要求的 3.x 配套方案。渲染节点register 注册自定义 Shapeantv/x6-react-shape的核心入口是register它把一个自定义shape名称与 React 组件绑定之后即可像使用内置节点一样通过graph.addNode添加。以下为文档配套示例的完整实现对应源码 site/src/tutorial/intermediate/react/basic/index.tsximport React from react import { Graph } from antv/x6 import { register } from antv/x6-react-shape import { Progress } from antd 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, }) const graph new Graph({ container: document.getElementById(container), background: { color: #F2F7FA }, }) graph.addNode({ shape: custom-basic-react-node, x: 60, y: 100, })register配置项的要点shape自定义节点类型名后续addNode与 JSON 数据中的shape字段都引用它width/height节点默认尺寸未在addNode中覆盖时生效component渲染节点内容的 React 组件可接收{ node }等 props见下节。注册后节点的渲染完全交给 React 组件Progress、Dropdown、Button等任意组件库都可直接内嵌无需关心 SVG 细节。更新节点effect 驱动的响应式重渲染节点内容常常需要随数据变化而更新。与核心 HTML 节点类似register支持传入effect字段——它是当前节点props名称的数组。当effect中任一 prop 发生变化时对应的 React 组件会被重新渲染该机制源自核心库 src/shape/html.ts 中监听change:*事件并判断effect.includes(key)的逻辑x6-react-shape 沿用同一约定。下面以data作为响应式数据源每秒递增进度值对应源码 site/src/tutorial/intermediate/react/update/index.tsximport React from react import { Graph, Node } from antv/x6 import { register } from antv/x6-react-shape import { Progress } from antd const NodeComponent ({ node }: { node: Node }) { const { progress } node.getData() return ( div classNamereact-node Progress typecircle percent{progress} width{80} / /div ) } register({ shape: custom-update-react-node, width: 100, height: 100, effect: [data], component: NodeComponent, }) const graph new Graph({ container: document.getElementById(container), background: { color: #F2F7FA }, }) 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)这里有两个值得注意的设计组件内取数NodeComponent接收nodeprop通过node.getData()读取当前数据而不是在组件外部闭包捕获——这样重渲染时永远拿到最新值effect 是更新开关effect: [data]表示仅当dataprop 变化时才重渲染。若未配置effect则在 X6 的 HTML 节点语义下按默认策略响应变更配置后能精确控制重渲染粒度避免无关属性变更触发无谓的组件重绘。data是任意 JSON 数据示例中为{ progress: number }也可将effect指向attrs、label等其他节点 props按需扩展响应式范围。Portal 模式让节点访问外部 Context直接渲染方式存在一个天然限制组件会被直接渲染到节点自身的 DOM 容器中底层相当于import { createRoot, Root } from react-dom/client const root createRoot(container) // container 为节点容器 root.render(component)这意味着组件不在应用正常的 React 渲染树中无法访问外部的Context如全局主题、国际化 locale、状态管理 Provider 等。若你的 React 组件依赖这些 Context请改用 Portal 模式。Portal 模式通过getProvider()获取一个 Provider 组件将其挂载在应用渲染树的 Context 层级之下节点组件即通过 Portal 挂到该 Provider 下。完整示例对应源码 site/src/tutorial/intermediate/react/portal/index.tsximport React from react import { Graph } from antv/x6 import { register, getProvider } from antv/x6-react-shape import { Progress, Button } from antd 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, }) export default class Example extends React.Component { private container: HTMLDivElement state { progress: 30 } componentDidMount() { const graph new Graph({ container: this.container, background: { color: #F2F7FA }, }) graph.addNode({ shape: custom-portal-react-node, x: 60, y: 100, }) graph.centerContent() } changeProgress () { this.setState({ progress: (this.state.progress 10) % 100 }) } refContainer (container: HTMLDivElement) { this.container container } 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 ) } }使用要点getProvider()返回的X6ReactPortalProvider必须包裹在你要共享的 Context Provider 内部一个 graph 只能声明一个 portal provider节点内的NodeComponent通过useContext(ProgressContext)读取外部 Context且与页面上的按钮等组件共享同一份状态——示例中点击 Add 按钮改变progress节点内的进度环会同步更新页面级 Context主题、多语言、状态库都能以同样的方式穿透到节点组件内部。实战场景用 React 节点实现右键菜单在快速上手教程中见 site/docs/tutorial/getting-started.zh.md 的 React 节点小节演示了一个典型场景给节点加右键菜单。用 SVG 手工实现菜单成本极高而借助 React 节点只需把组件包一层Dropdown完整源码 site/src/tutorial/getting-started/react-shape/index.tsxconst CustomComponent ({ node }: { node: Node }) { const label node.prop(label) return ( Dropdown menu{{ items: [ { key: copy, label: 复制 }, { key: paste, label: 粘贴 }, { key: delete, label: 删除 }, ], }} trigger{[contextMenu]} div classNamecustom-react-node{label}/div /Dropdown ) } register({ shape: custom-react-node, width: 100, height: 40, component: CustomComponent, }) graph.fromJSON({ nodes: [ { id: node1, shape: custom-react-node, x: 40, y: 40, label: hello }, { id: node2, shape: custom-react-node, x: 160, y: 180, label: world }, ], edges: [ { shape: edge, source: node1, target: node2, label: x6, attrs: { line: { stroke: #8f8f8f, strokeWidth: 1 } }, }, ], })注意这里通过node.prop(label)读取节点 label与getData()一样是节点 props 的读取入口注册、JSON 加载、组件取数三个环节串成了完整的声明式节点开发链路。小结与进一步阅读本文覆盖了 React 节点的完整闭环渲染register({ shape, width, height, component })注册自定义节点addNode({ shape, x, y })实例化更新effect: [data]声明响应式 prop组件内用node.getData()读、node.setData()写实现按需重渲染ContextgetProvider()配合 Context Provider 使用 Portal 模式让节点组件融入应用渲染树。相关英文版教程见 site/docs/tutorial/intermediate/react.en.md如果想从零熟悉 X6 的安装、建图与 JSON 数据加载可先阅读 快速上手若需深入理解 React 节点背后的 HTML/foreignObject 渲染机制可研读核心实现 src/shape/html.ts。【免费下载链接】X6 JavaScript diagramming library that uses SVG and HTML for rendering.项目地址: https://gitcode.com/GitHub_Trending/x6/X6创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表