切换到图谱标签时初始化
这个示例把 relation-graph 嵌入一个三状态页面,并延迟到用户打开 Graph 标签时才进行图挂载与数据初始化。它使用 `RGHooks.useGraphInstance()` 加载扁平内联数据、补全缺失连线 id,并在首次可见后立即执行居中与视口适配。
在标签页首次显示时初始化图谱
这个示例构建了什么
这个示例构建了一个全高页面,其中包含三个互斥面板:Basic Info、Graph 和 Warning Info。用户在首次加载时不会看到图谱。页面会先打开在一个绿色占位面板上,只有在选中 Graph 标签时,才会切换到一个从左到右的树形图。
这个示例的重点是生命周期控制,而不是图谱样式。它展示了如何在面板变为可见之前不把 RelationGraph 放入 DOM,然后在该面板首次可见时只初始化一次数据,并立刻让首帧可见渲染居中并适配视口。
数据如何组织
图谱数据直接在 initializeGraph() 内部声明为一个 RGJsonData 对象,其中包含 rootId: 'a'、13 个扁平的 nodes,以及 12 个扁平的 lines。树结构是通过 from 和 to 配对表达的,而不是通过嵌套的 children。
加载前只有一个预处理步骤:代码会遍历每一条 line,并在缺少 id 时为其补上一个。之后,数据集会被直接传给 setJsonData()。在真实应用中,相同的结构可以表示记录依赖、故障排查分支、审批链路,或者任何图谱只是更大信息页面中次级标签页的详情界面。
relation-graph 的使用方式
index.tsx 使用 RGProvider 包裹整个示例,而 MyGraph.tsx 通过 RGHooks.useGraphInstance() 获取当前活动实例。可见图谱被配置为一个从左到右的树,参数包括 treeNodeGapH: 120、treeNodeGapV: 20、矩形节点、defaultNodeWidth: 100、RGLineShape.StandardCurve、RGJunctionPoint.lr,以及位于右侧的展开控制点。
这里没有使用自定义节点、连线、画布或视口插槽。关键模式是延迟的实例驱动加载:只有在图谱标签激活之后,setJsonData() 才会注入数据,随后 moveToCenter() 和 zoomToFit() 会规范化首个可见画面。SCSS 文件作为覆盖样式脚手架存在,但在这个示例中并没有对图谱进行实质性的重绘样式。
图谱是按条件嵌入的,而不是永久挂载。一个本地 SimpleUISelect 组件控制 activeTabName,只有当 activeTabName === 'graph' 时才会渲染 RelationGraph,并且一个受 graphInitedRef 保护的 useEffect() 会确保初始化流程只在图谱标签首次激活时运行一次。根据已审阅的源码,无法确定离开标签页后再次进入时图谱状态是否会保留。
关键交互
- 点击选择器可在
Basic Info、Graph和Warning Info之间切换。 - 首次切换到
Graph时会挂载RelationGraph,构建内联数据集,通过setJsonData()加载它,然后让视口居中并适配。 - 切换到
Basic Info或Warning Info时,会用占位内容替换图谱面板,而不是仅通过 CSS 把图谱隐藏起来。 - 选择器本身是一个可复用的本地组件,其激活态样式由
currentValue驱动。
关键代码片段
这个包装器说明页面和图谱组件共享同一个 relation-graph provider 上下文。
const Demo = () => {
return (
<RGProvider>
<MyGraph />
</RGProvider>
);
};
这段代码表明,可见图谱是一个从左到右的树,使用矩形节点和曲线连线。
const graphOptions: RGOptions = {
layout: {
layoutName: 'tree',
from: 'left',
treeNodeGapH: 120,
treeNodeGapV: 20
},
defaultExpandHolderPosition: 'right',
defaultNodeShape: RGNodeShape.rect,
defaultNodeWidth: 100,
defaultLineShape: RGLineShape.StandardCurve,
defaultJunctionPoint: RGJunctionPoint.lr
};
这段代码证明图谱载荷采用的是扁平的内联 nodes 和 lines 结构,而不是嵌套的 children。
const myJsonData: RGJsonData = {
rootId: 'a',
nodes: [
{ id: 'a', text: 'a' },
{ id: 'b', text: 'b' },
{ id: 'b1', text: 'b1' },
// ... more nodes ...
],
lines: [
{ from: 'a', to: 'b', text: 'line1' },
// ... more lines ...
]
};
这段代码展示了唯一的预处理步骤,以及首次加载后立即进行的视口规范化。
myJsonData.lines.forEach((line, index) => {
if (!line.id) {
line.id = `line-${index}`;
}
});
await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();
这个 effect 是核心生命周期模式:在图谱标签激活之前什么都不做,激活后也只初始化一次。
useEffect(() => {
if (activeTabName === 'graph') {
if (!graphInitedRef.current) {
graphInitedRef.current = true;
initializeGraph();
}
}
}, [activeTabName]);
这个渲染分支让图谱成为三态工作区中的一个面板,而不是页面的永久展示面。
{activeTabName === 'graph' && (
<div className="h-full">
<RelationGraph options={graphOptions} />
</div>
)}
{activeTabName === 'warning' && (
<div className="h-full bg-yellow-100 flex justify-center place-items-center text-4xl">
Warning Information
</div>
)}
这个示例的独特之处
对比数据将这个示例归在 customize-fullscreen-action、tree-data 和 graph-instance-api 附近,它们都共享 provider 作用域的实例访问、树形渲染以及加载后的居中处理。adv-hide-2-show 的区别在于首次可见生命周期模式:RelationGraph 在用户选择 Graph 标签前并不存在,随后示例会加载一个扁平的内联数据集、补全缺失的 line id,并在首次显示之后立刻规范化视口。
与 customize-fullscreen-action 相比,这个示例关注的不是包装器组合或全屏目标,而是在三个全高内容面板之间切换,并聚焦于隐藏容器的时机控制。与 tree-data 相比,它强调延迟显示以及扁平的 nodes 加 lines 数据,而不是使用嵌套 children 后立即挂载。与 graph-instance-api 相比,它虽然使用了相同的 hook 和实例 API,但用途仅限于首次显示和视口初始化,而不是持续性的程序化展开或折叠控制。
在更简单的占位面板类示例中,这里的独特组合是由标签驱动的延迟显示加一次性初始化保护。这使它更适合作为这样的页面起点:图谱只是一个可选的检查模式,而不是页面默认展示的主体。
这种模式还适用于哪里
这种模式可以直接迁移到标签页、抽屉、手风琴、步骤器以及模态详情视图中,在这些场景里,如果图谱容器处于隐藏状态,就不应初始化图谱。它同样适用于混合内容的记录页面,用户可以先查看摘要或警告信息,再把图谱作为次级分析面板打开。
同样的结构也适用于 API 驱动加载。应用程序不必使用硬编码数据,而是可以在图谱标签激活时才请求关系数据,在加载前补齐缺失的边 id,然后调用居中和适配操作,使首个可见画面在出现时就已经可用。