JavaScript is required

切换到图谱标签时初始化

这个示例把 relation-graph 嵌入一个三状态页面,并延迟到用户打开 Graph 标签时才进行图挂载与数据初始化。它使用 `RGHooks.useGraphInstance()` 加载扁平内联数据、补全缺失连线 id,并在首次可见后立即执行居中与视口适配。

在标签页首次显示时初始化图谱

这个示例构建了什么

这个示例构建了一个全高页面,其中包含三个互斥面板:Basic InfoGraphWarning Info。用户在首次加载时不会看到图谱。页面会先打开在一个绿色占位面板上,只有在选中 Graph 标签时,才会切换到一个从左到右的树形图。

这个示例的重点是生命周期控制,而不是图谱样式。它展示了如何在面板变为可见之前不把 RelationGraph 放入 DOM,然后在该面板首次可见时只初始化一次数据,并立刻让首帧可见渲染居中并适配视口。

数据如何组织

图谱数据直接在 initializeGraph() 内部声明为一个 RGJsonData 对象,其中包含 rootId: 'a'、13 个扁平的 nodes,以及 12 个扁平的 lines。树结构是通过 fromto 配对表达的,而不是通过嵌套的 children

加载前只有一个预处理步骤:代码会遍历每一条 line,并在缺少 id 时为其补上一个。之后,数据集会被直接传给 setJsonData()。在真实应用中,相同的结构可以表示记录依赖、故障排查分支、审批链路,或者任何图谱只是更大信息页面中次级标签页的详情界面。

relation-graph 的使用方式

index.tsx 使用 RGProvider 包裹整个示例,而 MyGraph.tsx 通过 RGHooks.useGraphInstance() 获取当前活动实例。可见图谱被配置为一个从左到右的树,参数包括 treeNodeGapH: 120treeNodeGapV: 20、矩形节点、defaultNodeWidth: 100RGLineShape.StandardCurveRGJunctionPoint.lr,以及位于右侧的展开控制点。

这里没有使用自定义节点、连线、画布或视口插槽。关键模式是延迟的实例驱动加载:只有在图谱标签激活之后,setJsonData() 才会注入数据,随后 moveToCenter()zoomToFit() 会规范化首个可见画面。SCSS 文件作为覆盖样式脚手架存在,但在这个示例中并没有对图谱进行实质性的重绘样式。

图谱是按条件嵌入的,而不是永久挂载。一个本地 SimpleUISelect 组件控制 activeTabName,只有当 activeTabName === 'graph' 时才会渲染 RelationGraph,并且一个受 graphInitedRef 保护的 useEffect() 会确保初始化流程只在图谱标签首次激活时运行一次。根据已审阅的源码,无法确定离开标签页后再次进入时图谱状态是否会保留。

关键交互

  • 点击选择器可在 Basic InfoGraphWarning Info 之间切换。
  • 首次切换到 Graph 时会挂载 RelationGraph,构建内联数据集,通过 setJsonData() 加载它,然后让视口居中并适配。
  • 切换到 Basic InfoWarning 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
};

这段代码证明图谱载荷采用的是扁平的内联 nodeslines 结构,而不是嵌套的 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-actiontree-datagraph-instance-api 附近,它们都共享 provider 作用域的实例访问、树形渲染以及加载后的居中处理。adv-hide-2-show 的区别在于首次可见生命周期模式:RelationGraph 在用户选择 Graph 标签前并不存在,随后示例会加载一个扁平的内联数据集、补全缺失的 line id,并在首次显示之后立刻规范化视口。

customize-fullscreen-action 相比,这个示例关注的不是包装器组合或全屏目标,而是在三个全高内容面板之间切换,并聚焦于隐藏容器的时机控制。与 tree-data 相比,它强调延迟显示以及扁平的 nodeslines 数据,而不是使用嵌套 children 后立即挂载。与 graph-instance-api 相比,它虽然使用了相同的 hook 和实例 API,但用途仅限于首次显示和视口初始化,而不是持续性的程序化展开或折叠控制。

在更简单的占位面板类示例中,这里的独特组合是由标签驱动的延迟显示加一次性初始化保护。这使它更适合作为这样的页面起点:图谱只是一个可选的检查模式,而不是页面默认展示的主体。

这种模式还适用于哪里

这种模式可以直接迁移到标签页、抽屉、手风琴、步骤器以及模态详情视图中,在这些场景里,如果图谱容器处于隐藏状态,就不应初始化图谱。它同样适用于混合内容的记录页面,用户可以先查看摘要或警告信息,再把图谱作为次级分析面板打开。

同样的结构也适用于 API 驱动加载。应用程序不必使用硬编码数据,而是可以在图谱标签激活时才请求关系数据,在加载前补齐缺失的边 id,然后调用居中和适配操作,使首个可见画面在出现时就已经可用。