画流程图不一定要拖鼠标。用 Mermaid,你只要会打字,就能在 Markdown 文档里画出流程图、时序图、状态图。
Mermaid 是什么
Mermaid 是一个「用文字画图」的工具:你用一套约定好的文字描述图形,渲染器负责把它画出来。因为它就是普普通通的代码块,所以能直接跟着 Markdown 文档一起保存、一起复制、一起用 Git 管理。
在 Markdown 里这样写:
```mermaidflowchart TD A[开始] --> B[结束]```第一行 flowchart TD 是「画一张流程图,方向从上到下」,后面的每一行都是一条连线。就这么简单。
TIP写完想立刻看到效果,可以丢进 mermaid.live 预览,或者用 VS Code 的 Markdown 预览、Typora、Obsidian 这些自带 Mermaid 渲染的编辑器。
第一个流程图
flowchart TD A[开始] --> B[输入数据] B --> C{数据合法吗} C -- 合法 --> D[保存] C -- 不合法 --> E[报错]拆开看只有三件事:
| 部分 | 作用 |
|---|---|
flowchart TD | 声明图类型与方向,必须是第一行 |
A[开始] | 定义一个节点,A 是节点 id,方括号里是要显示的文字 |
A --> B | 连接两个节点,--> 表示带箭头的实线 |
节点 id 只是一个代号,图上不会显示它。同一个 id 写两次不会重复出现,而是指向同一个节点——所以你可以先连线、后定义文字,顺序随便。
方向:图往哪边长
把 flowchart TD 里的方向改掉,整张图的走向就变了:
| 写法 | 方向 |
|---|---|
TD 或 TB | 从上到下(默认,最常用) |
BT | 从下到上 |
LR | 从左到右(画流程条、时间线时很顺手) |
RL | 从右到左 |
flowchart LR A[需求] --> B[开发] --> C[测试] --> D[上线]你会注意到这里写成了 A --> B --> C --> D,一条链上可以连续写多个箭头,不用一行一行拆开。
节点:给方块换形状
光有方框太单调,Mermaid 给你准备了各种形状,靠「用什么括号包住文字」来区分:
| 写法 | 形状 | 一般用来表示 |
|---|---|---|
A[文字] | 矩形 | 普通步骤 |
A(文字) | 圆角矩形 | 步骤(柔和一点) |
A([文字]) | 胶囊形 | 开始 / 结束 |
A[[文字]] | 双边框 | 子流程 |
A[(文字)] | 圆柱 | 数据库 |
A((文字)) | 圆形 | 连接点 |
A{文字} | 菱形 | 判断分支 |
A{{文字}} | 六边形 | 准备 / 配置 |
A[/文字/] | 平行四边形 | 输入输出 |
A[\文字\] | 反向平行四边形 | 输入输出(反向) |
A[/文字\] | 梯形 | 手动操作 |
A>文字] | 旗帜形 | 备注 |
flowchart TD A([开始]) --> B[/输入账号/] B --> C{账号存在吗} C -- 否 --> D[提示注册] C -- 是 --> E[(查询数据库)] E --> F((完成))CAUTION圆括号、方括号、花括号这些成对符号是语法的一部分。如果节点文字里本身就有括号,一定要用双引号把文字包起来:
A["读取文件 (config.json)"]
连线:实线、虚线、加粗
| 写法 | 效果 |
|---|---|
A --> B | 实线箭头 |
A --- B | 实线,无箭头 |
A -.-> B | 虚线箭头 |
A ==> B | 加粗箭头 |
A --x B | 末端是叉号 |
A --o B | 末端是圆点 |
A o--o B | 两端都是圆点 |
虚线常用来表示异步、可选或「返回」的流程,加粗则用来强调主链路:
flowchart LR A[下单] ==> B[支付] -.-> C[异步发货] A --x D[取消订单]在连线上写字
有两种写法,效果一样,挑顺手的用:
A -->|文字| BA -- 文字 --> Bflowchart TD A{今天要出门吗} -- 要 --> B[看天气] A -->|不要| C[继续躺平] B --> D{下雨吗} D -- 下 --> E[带伞] D -. 不下 .-> F[直接走]注意虚线上写字时,中间也要用点:-. 文字 .->。
TIP连线上的文字里出现空格也没关系,
-- 数据合法 -->是合法写法。但文字里如果带|或括号,建议改用-->|文字|这种形式会更稳。
换行与注释
- 节点文字换行:直接用
<br>,例如A["第一行<br>第二行"] - 注释:以
%%开头的整行会被忽略,不会出现在图上
flowchart TD A["处理订单<br>(校验库存)"] --> B[发货] %% 这一行是注释,不会显示子图:把一组节点圈起来
用 subgraph 加 end 把若干节点包起来,就成了一块带标题的区域,特别适合画「系统分层」或者「谁负责哪一段」:
flowchart TD subgraph 客户端 A[浏览器] --> B[页面] end subgraph 服务端 C[接口] --> D[(数据库)] end B --> C几点细节:
subgraph 标题后面可以直接跟标题文字,也可以写成subgraph id [标题]- 每个
subgraph都必须有对应的end收尾 - 子图内部可以单独用
direction LR指定方向,不影响外面
样式:上色与强调
对节点上色有两种方式,推荐用 classDef 定义好一套样式,再批量套用:
flowchart TD A[正常流程] --> B{判断} B -- 异常 --> C[失败处理] classDef danger fill:#ffe3e3,stroke:#e06666,stroke-width:2px,color:#900 class C danger| 语法 | 作用 |
|---|---|
classDef 名字 fill:#色值,stroke:#色值 | 定义一套样式 |
class 节点 名字 | 给单个节点套样式 |
class A,B,C 名字 | 给多个节点套同一套样式 |
style 节点 fill:#色值 | 直接给单个节点写内联样式 |
linkStyle 0 stroke:#色值 | 给第 1 条连线(从 0 开始数)上色 |
fill 是填充色,stroke 是边框色,color 是文字颜色,stroke-width 是边框粗细,stroke-dasharray: 5 5 可以把边框画成虚线。
常见坑
- 文字里有括号:必须加双引号,
A["步骤 (1)"],否则报语法错误。 - 文字里有中文标点:全角括号
()一般没问题,半角()才会被当语法。 end冲突:节点文字正好是end(全小写)时,老版本会把它当成子图结束符,加引号写成A["end"]即可。- 节点 id 里的空格:id 尽量用
A、step1、check这类纯字母数字,中文和空格都放进括号里。 - 箭头方向写反:
A --> B是 A 指向 B,别按阅读顺序想当然。 - 渲染不出来:先确认代码块的语言标记写的是
mermaid,且flowchart是这一块的第一行。
完整例子:登录流程
把前面学的拼起来,就是一张能直接用的流程图:
flowchart TD Start([开始]) --> Input[/输入账号密码/] Input --> Check{账号密码正确?} Check -- 否 --> Retry{错误次数 < 3?} Retry -- 是 --> Input Retry -- 否 --> Lock[锁定账号] Check -- 是 --> MFA{需要二次验证?} MFA -- 否 --> Home[进入主页] MFA -- 是 --> Code[/输入验证码/] Code --> Verify{验证码正确?} Verify -- 是 --> Home Verify -- 否 --> Retry Home --> Done([结束]) Lock --> Done
classDef bad fill:#ffe3e3,stroke:#e06666,color:#900 class Lock bad速查表
flowchart TD %% 图类型 + 方向:TD/TB/BT/LR/RLA[矩形] A(圆角) A([胶囊]) A[[子流程]] A[(数据库)]A((圆)) A{菱形} A{{六边形}} A[/平行/] A>旗帜]
A --> B %% 实线箭头A --- B %% 实线无箭头A -.-> B %% 虚线箭头A ==> B %% 加粗箭头A -- 文字 --> B %% 带文字的实线A -. 文字 .-> B %% 带文字的虚线A -->|文字| B %% 带文字的另一种写法
subgraph 标题 ... end %% 子图%% 注释classDef 名字 fill:#色值,stroke:#色值class 节点 名字到这儿语法就够用了。剩下的就是多画几张——把平时口头讲的「先这样、再那样、不行就重来」翻译成节点和箭头,流程图自然就出来了。