在前端项目中,我们经常需要把系统结构、类关系或接口调用流程直观地展示出来。用JavaScript动态生成UML图表,本质是把文本化的模型描述在浏览器里实时转成图形,避免手工画图带来的版本脱节问题。这类方案既能嵌入文档站点,也能用在低代码配置面板里。

一、为什么选择声明式文本生成UML
传统做法是设计师用工具导出PNG,再贴到Wiki。一旦代码重构,图就过期了。声明式思路让UML和代码仓库放一起,用类似注释的语法描述,构建或运行时渲染。这样图永远跟着逻辑走,也方便做差异对比。
从实现看,文本转图形分两步:先按规则解析成节点和边的数据模型,再做布局算法算出坐标,最后用SVG或Canvas绘制。前端常用的mermaid把这两步都封装好了,调用方只写字符串。
二、使用mermaid快速绘制
mermaid是目前最轻量的前端UML库之一,支持类图、时序图、流程图等。引入后,只需在页面放一个带特定标识的容器,调用初始化函数即可。
下面示例展示如何在HTML里用mermaid画一个最简类图,注意代码块内所有尖括号都已转义:
<div class="mermaid">
classDiagram
class User {
+String name
+login()
}
class Order {
+int id
+pay()
}
User "1" -- "*" Order : creates
</div>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
上述代码中,classDiagram声明类型,class定义类及成员,关系行写出多重性。mermaid在加载时扫描class="mermaid"的节点,把文本变SVG。它的优点是零构建依赖,缺点是复杂布局定制能力弱。
三、动态更新图表内容
真实场景里,图表数据可能来自接口。我们可以用JavaScript拼装定义文本,再让mermaid重渲染。
下面函数演示根据接口返回的类关系动态生成UML:
async function renderUMLFromAPI() {
const res = await fetch('https://api.ipipp.com/uml/classes');
const data = await res.json();
let text = 'classDiagramn';
data.classes.forEach(c => {
text += ' class ' + c.name + ' {n';
c.fields.forEach(f => text += ' +' + f + 'n');
text += ' }n';
});
data.relations.forEach(r => {
text += ' ' + r.from + ' --> ' + r.to + ' : ' + r.label + 'n';
});
const box = document.getElementById('uml');
box.removeAttribute('data-processed');
box.textContent = text;
window.mermaid.contentLoaded();
}
这里先把接口数据转成mermaid文本,清空旧图标记后赋给容器,再触发重解析。注意removeAttribute('data-processed')是mermaid避免重复渲染的内部标记,不清除会导致更新失效。
四、自研SVG方案的适用边界
如果团队不允许引入第三方库,或需要特殊交互,可用原生SVG API手绘。思路是维护节点数组和连线数组,用getBBox量文字尺寸,简单排成树或网格。
下面给出极简节点绘制片段:
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
function drawNode(x, y, label) {
const rect = document.createElementNS(svg.namespaceURI, 'rect');
rect.setAttribute('x', x);
rect.setAttribute('y', y);
rect.setAttribute('width', 100);
rect.setAttribute('height', 40);
const text = document.createElementNS(svg.namespaceURI, 'text');
text.setAttribute('x', x + 10);
text.setAttribute('y', y + 25);
text.textContent = label;
svg.appendChild(rect);
svg.appendChild(text);
}
drawNode(20, 20, 'Controller');
自研方式灵活,但布局、箭头、防重叠都要自己写,工作量远大于用mermaid。一般只在高度定制报表或离线工具里才值得。
五、方案对比与选型建议
我们把常见方式放在一张表里看差异:
| 方案 | 体积 | 定制性 | 上手成本 |
|---|---|---|---|
| mermaid | 小 | 中 | 低 |
| plantuml+wasm | 大 | 高 | 中 |
| 原生SVG | 零 | 极高 | 高 |
对大多数前端文档或内部平台,mermaid在成本和效果上最平衡。若已有后端plantuml服务,也可前端直连复用。原生SVG仅推荐给图表即核心产品的团队。
六、常见误区提醒
有人以为UML库能直接读源码反向工程,其实前端库都只认文本定义,反向解析需配合AST工具另写逻辑。另外,把<div>里内容当HTML渲染是错的,mermaid文本里的尖括号必须按普通字符处理,否则解析报错。
掌握这些,就能在项目中稳当地用JavaScript把UML图表做活,让架构可视化随代码一起演进。
JavaScriptUML图表mermaid修改时间:2026-08-10 06:12:30