
写技术文档时最劝退的环节往往是画图。尤其是流程图业务流程、算法分支、接口状态流转这些逻辑明明在脑子里已经想得很清楚一旦打开绘图软件摆方块、拉箭头、调对齐、改字号一套动作下来基本就忘了初衷。我自己带过不少新人他们写设计文档时花在过程图上的时间和代码差不多后来我们索性把团队文档里的图都切成了 Mermaid把图当作代码来写。趁这个周末整理一篇比较系统的 Mermaid 流程图教程从环境准备到语法拆解再到算法图、业务图和 ER 图的实战基本覆盖日常工作里会碰到的用法。Mermaid 本质是一个基于 JavaScript 的图表描述语言用户用类似 Markdown 的文本描述节点和连线渲染引擎负责生成矢量图。与 Visio、ProcessOn 这类图形化工具相比最大的不同是你写的不是图形文件而是图的源码天然能进 Git 做版本管理能嵌入 Markdown 文档修改时直接改文字而不是拉框线。Mermaid 的核心价值在于让“画图”变成“写图”让流程图的维护成本大幅下降。这篇教程适合想优化文档效率的研发和产品经理也适合刚开始接触流程图绘制的学生读完你应该能独立画出包含分支、回环、子图和样式控制的完整流程图。1. 为什么越来越多人把流程图当作代码来写1.1 图的本质是数据文本才是信息的可靠载体很多人在第一次接触 Mermaid 时会问同一个问题图形化工具拖拽不是更直观吗为什么非要用文本这里有一个容易被忽略的底层逻辑任何一张流程图本质上都是数据结构里的图由节点集合和边集合组成。节点是什么步骤边是什么跳转关系这些信息本身是结构化数据不是像素。图形化工具把数据藏在了复杂的文件格式和画布坐标里你拖动一个框背后改的其实是一堆坐标和连线关系但肉眼看不见。文本恰恰是表达结构化数据最直接的形式。用 Mermaid 写图写的是节点 ID、节点形状和连接关系布局交给引擎人的注意力集中在逻辑本身。这种做法带来的第一个实际好处是版本管理。图片格式的流程图在 Git 里就是一个二进制文件改动后只能看到“文件变了”却说不清变了什么。Mermaid 源码是文字每一次增删节点、调整分支在 diff 里看得一清二楚代码评审时顺带就能把图给评审掉文档和代码可以保持同一套协作流程。我在实际项目里感受最深的是文档一致性问题。以前用画图工具维护流程图改代码的时候很少有人记得同步改图几个月后图就彻底失真。现在图写在 Markdown 文档里和代码一起提交改逻辑的人必须顺手改图否则 review 阶段就会被发现。图不再是一个孤立的文件而是文档体系的一部分这比任何绘图技巧都重要。1.2 真正适合用 Mermaid 的场景清单虽然 Mermaid 很好用但不是什么图都该用它。我给自己定了一个取舍标准如果一张图的重点是表达逻辑结构用 Mermaid如果重点是视觉呈现用专业设计工具。按这个标准下面这些场景我基本都会直接用 Mermaid用户管理模块、登录鉴权、订单状态机这类软件流程分支和异常情况特别多文字化表达正好贴合程序员的思维方式。算法流程图包括 BFS/DFS 遍历、排序算法、判断一个数能否同时被 3 和 5 整除这种经典习题以及 ALNS 这类包含迭代过程的启发式算法。业务主线流程比如从采购到生产计划再到销售出货的跨部门流转用子图分组后非常清晰。数据库关系设计里的 ER 图实体和关系用文本描述比手动画线快太多。以及轻量级思维导图用来快速梳理思路完全够用。不太适合 Mermaid 的场景也有不少。组织结构图如果超过 100 个节点Mermaid 的自动布局会显得拥挤不如专门的组织架构软件。需要强烈视觉冲击力的宣传海报以及精细的 UI 交互原型也都不适合硬套 Mermaid。看清楚边界才知道工具到底该在哪个环节发力。2. 编辑器选型与运行环境准备2.1 mermaid.live 与离线编辑器的分工开始学 Mermaid 最简单的方式是打开官方在线编辑器 mermaid.live左边写语法右边实时渲染几乎零门槛。mermaid.live 免费没有类似 ProcessOn 免费版那种张数限制调试完成可以直接导出 PNG 或 SVG。我习惯先用它验证语法确认无误后再把代码粘进正式文档相当于一个快速的语法校验器。如果工作环境要求离线或者你希望把渲染集成到日常编辑器里我推荐三种方案。第一种是 VS Code 配合 Markdown Preview Mermaid Support 扩展打开 Markdown 预览面板就能实时看到图形适合写代码和写文档在同一环境里的开发者。第二种是 Typora它内置了 Mermaid 渲染写 Markdown 时直接敲代码块就能出图对写作体验最友好。第三种是 mermaid-cli 命令行工具它可以将 Mermaid 源码批量渲染成 SVG、PNG 甚至 PDF适合接入 CI 流水线文档构建时自动生成所有图表彻底解放人工导出的操作。这里有一个很容易踩的坑不要把在线编辑器里的渲染效果当作唯一标准。Mermaid 的语法在 mermaid.live 上通常是最新版本但你的本地编辑器内置版本可能落后一两个大版本某些新特性在本地渲染不出来。我的经验是先确认目标平台支持的是哪个 Mermaid 版本再决定能不能使用新语法而不是拿到一段能跑的代码就往文档里塞。2.2 Typora 如何更新 Mermaid 版本有读者问过 Typora 如何更新 Mermaid 版本这个问题的答案稍微有点绕。Typora 是闭源软件内置的 Mermaid 引擎和编辑器本身打包在一起用户没有办法单独替换 Mermaid 版本。你只能等待 Typora 官方在版本更新时升级它打包的 Mermaid 引擎。如果你是因为某个新语法在 Typora 里渲染失败才想更新我建议先做两步判断。第一步把代码丢到 mermaid.live 里跑一下如果在官方在线编辑器里也报错说明语法本身有问题跟 Typora 无关。第二步如果 mermaid.live 正常而 Typora 失败说明是 Typora 内置版本过旧。最直接的办法是更新 Typora 到最新版本一般过一段时间就会解决。如果你暂时不想升级 Typora也可以先用 VS Code 的 Mermaid 预览扩展来确定最终图形效果再决定是否调整语法。实际上Mermaid 的更新缺口在多数 Markdown 渲染器里都存在不只是 Typora提前用在线编辑器验证是成本最低的排查方式。2.3 在 Markdown、GitHub 和 GitLab 中嵌入图形Mermaid 最常见的嵌入方式是在 Markdown 里插入一个代码块语言标记写成 mermaid渲染器会自动把它解析成图形。GitHub 和 GitLab 的 Markdown 都原生支持 Mermaid仓库里的 README 和文档可以直接放图这对开源项目来说非常方便。你在 GitHub 上看到的内嵌流程图很多就是靠这个机制渲染的。需要留意的是不同平台的渲染支持程度不一样。GitHub 只支持部分 Mermaid 图表类型和语法特性GitLab 的支持也在逐步收紧。如果一段代码在 mermaid.live 和 Typora 里都正常但推上去以后显示不了往往是平台安全策略过滤掉了一些特性比如点击跳转链接或者某些 HTML 标签。我的建议是文档里优先使用最基础的语法减少 onclick、style 这类高级特性图表内容表达清楚永远比花哨更重要。3. Mermaid 流程图核心语法从节点到分支回环3.1 先搞懂节点形状和方向流程图的核心语法其实很少入门只需要掌握 flowchart 声明、节点定义和连线。第一行写flowchart TD表示这是一张方向为自上而下的流程图常用方向有三种TD和TB都是从上往下LR是从左往右。算法题和业务审批流用TD多系统架构类的横向流程用LR更合适。节点定义的格式是ID[显示文字]方括号代表矩形节点这是最常用的普通步骤。不同括号代表不同形状我整理了一张速查表写法形状常见用途A[普通步骤]矩形一般处理逻辑A(开始或结束)圆角矩形流程起止、温和提示A{条件判断}菱形分支判断A[[子流程]]双矩形子程序调用A[(数据库)]圆柱体数据存储A((节点))圆形事件节点、状态点节点 ID 可以随意命名建议用有语义的英文或者拼音缩写方便后续维护。显示文字则写成中文或业务描述渲染的时候显示的是括号里的内容。有一个很容易踩的坑节点 ID 最好全表唯一。我见过不少新手在不同地方重用了同一个 ID结果 Mermaid 会把它们合并导致连线乱成一团。3.2 连线语法实线、虚线、粗线与标注连线是流程图里表达逻辑关系的核心Mermaid 的连线语法非常直白。最简单的A -- B就是从 A 指向 B 的实线箭头绝大多数流程都在用这一条。在此基础上还有几种变体我记得刚接触时最先要记的是下面这组A -- B 实线箭头默认连线 A --- B 实线无箭头表示相邻关系 A -.- B 虚线箭头通常表示可选路径 A B 粗箭头表示重点流程 A -- 是 -- B 带文字的实线箭头 A -. 可选 .- B 带文字的虚线箭头 A 失败 B 带文字的粗箭头带文字的连线特别重要因为流程图里分支条件就是靠这些文字表达清楚的。系统会自动在线上把文字显示出来比如从判断节点出发一条线标“是”指向放行另一条线标“否”指向拒绝阅读的人不需要猜箭头含义。我也用过A --|是| B这种写法作用和A -- 是 -- B完全一样。个人建议整套文档统一用-- 是 --这种格式可读性更好也方便全局搜索替换。3.3 分支、循环回环和 subgraph 分组实际流程图很少是一条直线走到底判断分支和循环回环不可避免。判断分支直接用菱形节点承载每个出口带不同标签。循环回环稍微绕一些Mermaid 本身没有专门的 loop 关键字但你可以让低层节点重新指回上层节点从视觉上形成一个回路效果和编程里的循环一模一样。子图是我最喜欢的语法它可以把一组相关节点包在一个框里整个流程立刻变得有层次。下面这段代码模拟了登录模块的用户侧和服务端分组flowchart TD subgraph 用户侧 A[输入账号密码] -- B[提交请求] end subgraph 服务端 B -- C{账号密码校验} C -- 成功 -- D[返回登录凭证] C -- 失败 -- E[提示账号或密码错误] E -- A end这里subgraph 用户侧到end之间的节点都会被包进同一个区域区域自动加一个带边框的标题框。子图特别适合画微服务调用、模块划分、系统边界这类场景。需要注意子图的连线可以跨子图比如上面的 B 节点同时属于服务端子图但从用户侧的 A 连过来这种跨层连线偶尔会打乱自动布局如果发现图太乱先把连线简化再考虑调整分组。3.4 样式设置与 classDef让重点分支一目了然默认的 Mermaid 图所有节点都是浅色底、黑色框说实话信息密度高的时候看着很平。给关键节点上色能让阅读者第一眼就抓住重点。最简单的办法是使用 style 语句flowchart LR A[正常流程] -- B[异常处理] style A fill:#e1f5fe,stroke:#0277bd,color:#000 style B fill:#ffebee,stroke:#c62828,color:#000style 里可以设置填充色、边框色、边框粗细、文字颜色等常见视觉属性。颜色建议用十六进制色值具体配色没有标准只要保证“正常”和“异常”在视觉上有明显区分就行。我更推荐的做法是使用 classDef 定义可复用的样式类尤其是图里节点一多一个个写 style 会显得又长又难维护。classDef 的写法是先定义一个类再把节点归到类里classDef ok fill:#e8f5e9,stroke:#2e7d32,color:#000 classDef bad fill:#ffebee,stroke:#c62828,color:#000 class A ok class B bad如果图里需要区分多个状态比如待处理、处理中、已完成、失败用 classDef 定义四个类然后在节点上挂类名比在每个节点上重复写 style 干净得多。而且一旦要调整配色只用改 classDef 的定义位置全图跟着变这一点在长期维护的文档里价值尤其大。4. 实战用户模块、算法和业务流程图的画法4.1 用户管理模块流程图怎么搭用户管理是后台系统里最常见的模块也是搜索关键词里出现频率很高的画图需求。这类图的套路比较固定核心就是登录校验、状态判断、角色权限读取这几步。我一般把异常分支也完整画出来这样开发照着图实现时不会漏边界条件。下面这段代码可以作为用户登录流程的参考模板flowchart TD A[用户请求访问系统] -- B[进入登录页] B -- C[输入账号和密码] C -- D{账号密码校验} D -- 失败 -- E[提示账号或密码错误] E -- C D -- 成功 -- F{用户状态是否正常} F -- 禁用 -- G[拒绝登录并提示联系管理员] F -- 正常 -- H[读取用户角色权限] H -- I[生成登录会话] I -- J[进入系统首页]这里有几个经验点。首先是回到输入节点的回环密码错误时让用户重新输入这对应了实际的用户体验。其次是用户状态判断独立成节点把“校验密码”和“用户是否被禁用”分开逻辑上更清晰以后加“锁定”“过期”等状态时也只需要在这个节点扩展分支。第三权限读取放在登录成功之后很多人会忘记这一层结果页面权限全部写死在代码里。4.2 算法流程图判断整除、BFS/DFS 与 ALNS算法题和论文里画流程图有一个天然优势逻辑非常确定几乎没有歧义画起来反而比业务图更轻松。拿经典的“判断一个数 n 能否同时被 3 和 5 整除”举例核心是两次取模判断我习惯把取模结果作为判断条件而不是直接把整段运算写进菱形这样图形更整齐flowchart TD A[输入整数 n] -- B{n % 3 0} B -- 否 -- F[不能同时被3和5整除] B -- 是 -- C{n % 5 0} C -- 否 -- F C -- 是 -- D[可以同时被3和5整除]BFS 和 DFS 这类图的遍历算法也适合用 Mermaid 表达。BFS 的核心是队列和已访问集合流程图的关键在于循环判断我写的版本大致是下面这个结构flowchart TD A[将起点入队] -- B{队列是否为空} B -- 否 -- C[取出队首节点 u] C -- D{u 是否已访问} D -- 否 -- E[标记已访问并处理 u] E -- F[遍历 u 的所有邻居 v] F -- G{v 是否未访问} G -- 是 -- H[将 v 入队] H -- B G -- 否 -- F D -- 是 -- B B -- 是 -- I[遍历结束]第一次画这种图的时候容易陷入一个误区把所有细节都画进去结果连线交叉得没法看。我的做法是只保留算法主干的三个循环邻居遍历内部的具体操作全部隐藏需要细讲的部分另外拆一张子图。论文插图最忌讳的就是一图塞满所有信息这一点对算法流程图尤其适用。再举一个 ALNS 算法流程图这种元启发式算法的核心就是“破坏-修复”的迭代循环。用 Mermaid 画出来以后你立刻能看出哪些分支是高频循环flowchart TD A[生成初始解] -- B[初始化参数] B -- C{达到终止条件} C -- 否 -- D[选择破坏算子] D -- E[移除部分元素] E -- F[选择修复算子] F -- G[生成新解] G -- H{是否接受新解} H -- 是 -- I[更新当前解] I -- J{是否更新全局最优} J -- 是 -- K[更新全局最优解] J -- 否 -- C H -- 否 -- C C -- 是 -- L[输出全局最优解]画这种图时我建议把“终止条件”放在循环顶部而不是只在底部放一个判断因为大多数人在看算法时更习惯先了解什么时候停下来再进入循环体。这种布局也对应了代码里while (!stop)的判断结构。4.3 跨部门业务流程图从采购到生产到销售业务流程图是最讲究分阶段表达的我尤其喜欢在 SAP 风格的业务流程图里用子图划分阶段。比如从采购到 PS生产计划再到销售的完整链路可以拆成采购、生产、销售三个子图每个子图内部又有关键节点整体看下来条理非常清楚flowchart LR subgraph 采购阶段 A[采购申请] -- B[创建采购订单] B -- C[收货与质检] end subgraph 生产阶段 C -- D[生产计划] D -- E[生产执行] E -- F[产成品入库] end subgraph 销售阶段 F -- G[销售订单] G -- H[拣配与发运] H -- I[开票与结算] end业务流程图最大的坑是节点级别不统一。有人会把“采购申请”和“收货质检异常处理”放在同一个层级导致图形跳跃感很强。我的习惯是先统一所有节点的动词名词比如“创建采购订单”“执行生产计划”“创建销售订单”再决定哪些异常分支值得单独画。高层业务图中异常处理通常先一笔带过重点展示主链路的端到端流转细节放到下一级子流程图里。4.4 与 BPMN 网关模型的对应做流程管理的读者可能用过 BPMN 工具对“网关”这个概念很熟悉。BPMN 里有排他网关、并行网关、事件网关等建模符号语义非常严谨。Mermaid 的流程图并不会严格复刻这些符号它用菱形判断节点表达排他网关并行分支则需要手动拆分。如果你过去习惯用 BPMN 画流程切换到 Mermaid 时只需要记住一件事Mermaid 不强调网关的建模语法而是把判断和分支直接画出来。排他网关对应的是只有一条分支会被执行的菱形判断并行网关对应的是多个分支同时往下走的节点组合。需要严格建模 BPMN 并导出标准文件给工作流引擎执行的话Camunda Modeler 这类专门工具更合适。但如果只是给文档和评审用Mermaid 的表达已经足够清楚这也是我现在绝大多数场景直接选 Mermaid 的原因。5. 进阶ER 图、思维导图与源码流程图5.1 ER 图 30 秒上手Mermaid 不只是能画流程图它在数据建模方面也相当好用。用erDiagram声明 ER 图然后定义实体和关系比如常见的用户、订单、订单明细模型erDiagram USER ||--o{ ORDER : places ORDER ||--|{ ORDER_ITEM : contains USER { int id string username string email } ORDER { int id int user_id date created_at } ORDER_ITEM { int id int order_id string sku int quantity }关系符号是三段式最左边是基数最右边是基数。||表示“恰好一个”o{表示“零个或多个”|{表示“一个或多个”。比如USER ||--o{ ORDER读起来就是“一个用户对应零到多个订单”。这个语法初次接触容易记混我的记忆口诀是靠近实体的符号描述该实体这一侧的数量读的时候从左往右读成“一个 A 对应多少个 B”。ER 图对数据库设计评审特别有用实体字段直接在代码块下部列出类型和字段名一目了然。相比用图形工具逐个画表Mermaid 不仅快而且修改字段时直接改文字就行比拖拽图形省力气得多。5.2 思维导图和时间线Mermaid 新版本内置了 mindmap 图类型写起来和流程图完全不同用缩进表示层级很适合做头脑风暴记录。比如我规划一篇系统流程教程时脑内的结构可以直接映射成思维导图mindmap root((系统流程图教程)) 明确问题 输入与输出 边界条件 设计步骤 划分模块 确定判断点 绘制图形 选择方向 节点命名 检查逻辑 走通主路径 验证分支思维导图的优点是没有连线需要维护纯靠缩进决定层级对内容进行了结构化梳理。我有时候会把复杂需求先用思维导图拆一遍再把节点转为流程图里的步骤和判断整个思路顺畅很多。时间线图也有类似的价值用timeline关键字定义时间点适合写项目排期和里程碑回顾如果你平时要汇报项目计划值得一试。5.3 MyBatis 等源码流程图的画法心得搜索热词里有“mybatis 中 typehandler 的工作流程图”和“xmlconfigbuilder 的工作流程图”可见画源码流程是很多开发者的刚需。源码流程图的难点不在于 Mermaid 语法而在于自己怎么把代码执行路径拆成节点。以 MyBatis 的 TypeHandler 为例它本质上解决的是 Java 类型和 JDBC 类型之间的转换问题执行 SQL 时通过 ParameterHandler 调用核心调用路径可以简化成下面这张图flowchart LR A[MyBatis 执行 SQL] -- B[ParameterHandler 取得参数] B -- C{是否存在自定义 TypeHandler} C -- 是 -- D[调用 setParameter 设置 JDBC 参数] C -- 否 -- E[使用内置类型处理器] D -- F[PreparedStatement 绑定参数] E -- F F -- G[执行 SQL]画源码图我的方法分三步。第一步先只看接口和入口函数把调用链上的关键类列出来。第二步找出分支点比如“是否配置了自定义实现”“配置节点是否存在”这些分支点就是菱形节点。第三步把异常处理和默认兜底逻辑画成分支的另外一侧。用这个思路画 XMLConfigBuilder 也很顺手它解析 MyBatis 主配置文件的流程本质上就是一个“遍历子节点并分发处理”的模式子节点类型就是判断条件画出来的图形结构会非常接近源码里的分支结构。6. 常见问题与排查技巧实录6.1 中文乱码、括号与特殊字符的转义Mermaid 对中文的支持总体没问题节点里直接写中文是安全的。真正容易出问题的是特殊符号。比如节点文本里带括号、引号、百分号直接写会让解析器理解错边界。处理方式是用双引号把整个文本包起来写成A[登录(后台)]或者B{n % 3 0}Mermaid 就会把双引号里的内容当作一整个字符串。换行也是一个高频需求。节点文本太长会挤占整个画布我习惯在文本里手动加br/来换行比如A[第一行br/第二行]。不过要注意这种换行依赖渲染器是否支持 HTML 标签部分平台出于安全考虑会过滤掉导致换行失效。最稳妥的做法还是缩短节点文本把多余的描述放到流程图下方的文字说明里。6.2 图太宽溢出页面怎么办流程图渲染出来太宽是新手最容易遇到的问题。一张从上到下的流程图本来很窄但是如果某个分支文本特别长就会把整个画布横向扯得很宽在 Typora 和 VS Code 预览里只能拖动滚动条阅读体验很差。解决办法有几个我给一个优先级顺序。先把flowchart TD改成flowchart LR让主流程横向展开很多“过宽”问题其实是因为方向选择和内容长度不匹配。然后看节点文本是不是太啰嗦一个节点能写 10 个字的不要写 50 个字需要用长文本说明的部分挪到图例里写。最后是用 subgraph 分组把相关的节点收拢在一起减少跨区域连线。如果这样还是很宽最直接的办法是拆图把主流程拆成粗粒度的“主图”和细粒度的“子图”拆完的图反而更容易读。6.3 常见渲染错误与版本差异排查 Mermaid 问题可以用三个句号的经验来判断先确认语法再确认版本最后确认平台。三种情况对应不同的解决路径我整理成一张速查表遇到类似问题可以直接对照。典型症状常见原因解决方式Parse error代码完全不能渲染节点 ID 重复、括号未配对、文本里含未转义引号给出现问题的节点文本加双引号检查 ID 唯一性中文显示正常但导出图片乱码导出环境缺少中文字体或末设置字体设置 fontFamily 为中文字体或更换导出工具新语法在本地不渲染本地 Mermaid 版本过旧在 mermaid.live 验证语法更新 Typora 或 VS Code 插件图形布局非常混乱连线交叉过多、方向选择不当改用 LR 方向、简化连线数量、使用 subgraph 分组点击链接和样式失效平台安全策略禁用附加特性废弃 onclick、style 等功能保留纯流程图结构这里特别提醒一个版本坑Mermaid 升级到新版本后部分旧语法会发生变化。比如老版本里建议用graph TD新版本则更推荐flowchart TD。如果有人给你一份老 Mermaid 代码先跑一遍确认兼容性再合并进自己的文档。6.4 和其他绘图工具怎么选一张对照表市面上绘图工具很多有备选方案是好事但也容易选择困难。我把 Mermaid 和几款主流工具放在一起对比你自己按场景选就行工具文件本质协作方式适合场景Mermaid文本源码进 Git嵌 Markdown技术文档、代码评审、自动化文档PlantUML文本源码进 Git类 MermaidUML 和时序图团队统一draw.io / diagrams.net图形文件在线协作快速画一次性的架构图、组织结构图ProcessOn云端图形在线协作非技术团队画业务流程图Visio本地文件/云端微软生态企业级标准建模、复杂网络拓扑我自己的选择原则很简单如果图将来会被反复修改强调版本管理和内容协同选 Mermaid。如果只是临时画一张给同事看对方完全没接触过代码我会顺手用 draw.io。Mermaid 毕竟存在学习曲线哪怕它很好用也犯不着为了五分钟的事去开课。工具服务于目的能用顺手解决当前问题就是好选择。最后分享一个我坚持了很久的习惯拿到任何画图需求先打开一个空文本文件用列表把流程节点全部写出来再考虑要不要打开 Mermaid。很多新手直接打开画布才痛苦的回忆过程一旦陷入图形界面注意力就会从逻辑被拽回布局。先写文字步骤再翻译成 Mermaid等于给思维加了一道草稿缓冲处理好逻辑再谈绘图流程图上手速度会快很多。经验多了以后你甚至会发现 90% 的图根本不需要好看把分支画清楚把回环画完整比什么都重要。