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