5.3 KiB
5.3 KiB
节点包含表格时的渲染逻辑(MindMap 前端)
本文件汇总“当节点内容中有表格时”的数据流、渲染、样式、交互与导出路径,便于快速定位问题与修改。
一、总体流程
- 输入来源:
- Markdown 表格(GFM)
- 已有 HTML(
<table>)
- 转换阶段:
- Markdown → HTML:解析后输出
<table class="markdown-table">(附基础样式)。 - HTML → Markdown(需要时):优先用 Vditor 的
html2md;内置兜底逻辑会提取<table>为 GFM 格式。
- Markdown → HTML:解析后输出
- 节点渲染:
- 优先使用
dangerouslySetInnerHTML将 HTML 直接写入节点 DOM。 - 若是纯文本则走普通
topic文本渲染。
- 优先使用
- 样式覆盖:
- 统一为表格设置固定布局、边框、间距、
white-space: normal等,避免被思维导图默认排版影响。
- 统一为表格设置固定布局、边框、间距、
- 交互编辑:
- 双击含表格的节点 → 走“表格专用编辑”流程(弹出覆盖层,按 Markdown 表格编辑)。
- 图片导出(SVG):
- 发现
<table>时,导出使用foreignObject渲染,并内联样式与添加背景矩形,确保版式一致。
- 发现
二、数据来源与转换
- Markdown → HTML(保留为
<table>)- 位置:
frontend/src/components/MindMap.vue - 逻辑:将 GFM 表格替换为
<table class="markdown-table">,并生成<thead>/<tbody>与单元格基础内联样式。
- 位置:
- 渲染后统一后处理
- 位置:
frontend/src/utils/markdownRenderer.js - 逻辑:把裸
<table>补成<table class="markdown-table">,并处理代码块语法高亮等。
- 位置:
- HTML → Markdown(用于回填编辑器/导出)
- 位置:
frontend/src/components/MindMap.vue - 逻辑:若缺少 Markdown 源,优先
Vditor.html2md;否则解析 DOM,将<table>转回 GFM 表格(含表头/表体)。
- 位置:
示例 Markdown:
| A | B |
|---|---|
| 1 | 2 |
渲染为:
<table class="markdown-table">...
三、节点渲染优先级与更新
- 优先级:
dangerouslySetInnerHTML>markdown>topic文本。 - 直接写入 DOM:更新节点时,如果存在
dangerouslySetInnerHTML,直接nodeElement.innerHTML = dangerouslySetInnerHTML。 - 回退渲染:当内容不是 Markdown 时,回退渲染会先清理重复符号;若检测到
<table>,不做列表转换,直接保留表格结构。
涉及位置:
frontend/src/components/MindMap.vue(保存与“直接设置 HTML”)frontend/src/lib/mind-elixir/src/utils/dom.ts(回退渲染与表格检测)
四、样式与布局(确保表格按网格显示)
- 全局样式(保证在节点内渲染出的
<table>有固定布局/合并边框/边框色):frontend/src/App.vue中对.mind-elixir .map-container .topic table的规则。
- 组件内样式(覆盖思维导图的
white-space、display):frontend/src/components/MindMap.vue中.topic .topic-text.markdown-content table及th/td/tr规则。
- 统一
th/td的内边距、边框与交互高亮,避免被默认 inline 布局破坏行列结构。
五、交互:双击进入表格编辑
- 位置:
frontend/src/lib/mind-elixir/src/mouse.ts:双击节点时若innerHTML含<table>,走“表格编辑”。frontend/src/lib/mind-elixir/src/nodeOperation.ts:beginEdit内部判断表格后调用editTableNode。
- 编辑方式:
editTableNode弹出覆盖层,编辑 Markdown 表格源(包含 HTML↔Markdown 的转换工具)。
六、导出图片(SVG)中的表格渲染
- 位置:
frontend/src/lib/mind-elixir/src/plugin/exportImage.ts - 检测
dangerouslySetInnerHTML中是否含<table>:- 含表格:使用
foreignObject嵌入 HTML,计算节点尺寸,创建背景矩形,并将所需样式内联化以确保导出与画布一致;表格本身在foreignObject内按浏览器 HTML 布局渲染。 - 非表格 HTML:优先尝试原生 SVG 文本渲染;必要时退回
foreignObject。
- 含表格:使用
七、关键判断点一览
- 是否包含表格:
- 通过检测
'<table'、'<td>'、'<th>'或 Markdown 中的|来作出路径选择(如走表格编辑、使用foreignObject导出等)。
- 通过检测
- 渲染选择:
- 有
dangerouslySetInnerHTML→ 直接注入 HTML; - 否则尝试
markdown→marked/自定义解析; - 最后回退到纯文本
topic。
- 有
八、常见问题与建议
- 若表格在节点中“挤成一行”或“行列错乱”,优先检查是否有样式覆盖了:
display: table-*、white-space: normal !important、table-layout: fixed、border-collapse: collapse是否生效。
- 导出图片中表格错位:确认
foreignObject是否被禁用、样式是否已内联、节点尺寸计算是否准确。 - 需要统一风格时,优先改
.markdown-table与.topic .topic-text.markdown-content table相关样式。
相关文件清单(便于跳转)
frontend/src/components/MindMap.vuefrontend/src/utils/markdownRenderer.jsfrontend/src/lib/mind-elixir/src/utils/dom.tsfrontend/src/lib/mind-elixir/src/mouse.tsfrontend/src/lib/mind-elixir/src/nodeOperation.tsfrontend/src/lib/mind-elixir/src/plugin/exportImage.tsfrontend/src/App.vue