BPMNJS官方案例1:React 19 + TypeScript + BPMN 入门完整教程
# React 19 + TypeScript + BPMN 入门完整教程
这是一份**从零到实战**的教程,基于最新 **React 19** + **TypeScript**,带你快速掌握 BPMN 流程设计器的基础使用、渲染、编辑、保存、导出等核心功能,全程可直接复制运行。
## 一、前置知识 & 环境
1. 基础 React + TypeScript 语法
2. 已创建好 React 19 + TS 项目(`create-react-app` / `vite` 均可)
3. 核心依赖:
- `bpmn-js`:BPMN 渲染、建模核心库
- `bpmn-js-properties-panel`:右侧属性配置面板
- `@bpmn-io/properties-panel`:新版属性面板依赖
- `diagram-js`:BPMN 底层绘图库(自动依赖)
---
## 二、安装依赖
在项目根目录执行:
```bash
# 核心 BPMN 库
npm install bpmn-js
# 属性面板(用于编辑节点名称、ID、类型等)
npm install bpmn-js-properties-panel @bpmn-io/properties-panel
# 样式文件
npm install inherits-browser
```
完整的组件清单:

---
## 三、核心概念(新手必看)
1. **Viewer**:仅查看 BPMN 流程图(不可编辑)
2. **Modeler**:可编辑、拖拽、配置的流程设计器(本教程重点)
3. **XML**:BPMN 的数据格式(所有流程最终都是 XML 字符串)
4. **Canvas**:画布区域
5. **Properties Panel**:右侧属性配置面板
---
## 四、基础版:BPMN 流程图查看器(Viewer)
先实现**只读展示**,理解 BPMN 渲染原理。
### 1. 创建组件 `BpmnViewer.tsx`
```tsx
import { useEffect, useRef } from 'react';
import BpmnViewer from 'bpmn-js';
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
// 示例 BPMN XML(默认空流程)
const defaultBpmnXml = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL http://www.omg.org/spec/BPMN/2.0/20100524/BPMN20.xsd">
<bpmn2:process id="Process_1" isExecutable="false">
<bpmn2:startEvent id="StartEvent_1" />
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>`;
const BpmnViewer = () => {
const containerRef = useRef<HTMLDivElement>(null);
const viewerRef = useRef<BpmnViewer | null>(null);
// 初始化 Viewer
useEffect(() => {
if (!containerRef.current) return;
// 创建实例
const viewer = new BpmnViewer({
container: containerRef.current,
width: '100%',
height: '600px',
});
viewerRef.current = viewer;
// 渲染 XML
viewer.importXML(defaultBpmnXml).catch((err) => {
if (err) console.error('BPMN 渲染失败', err);
});
// 销毁
return () => {
viewer.destroy();
};
}, []);
return (
<div style={{ border: '1px solid #eee' }}>
<h3>BPMN 查看器(只读)</h3>
<div ref={containerRef} style={{ width: '100%', height: '600px' }} />
</div>
);
};
export default BpmnViewer;
```
### 2. 在 App 中使用
```tsx
import BpmnViewer from './BpmnViewer';
function App() {
return (
<div style={{ padding: 20 }}>
<BpmnViewer />
</div>
);
}
export default App;
```
运行项目,你会看到一个**基础启动事件**的流程图,**不可编辑**。
显示如下:

---
## 五、进阶版:可编辑 BPMN 设计器(Modeler)+ 属性面板
这是**企业最常用**的功能:
- 左侧工具栏拖拽节点
- 右侧编辑节点属性
- 保存/导出 XML
- 导出 SVG 图片
### 1. 创建组件 `BpmnModeler.tsx`
```tsx
import { useEffect, useRef, useState } from 'react';
import Modeler from 'bpmn-js/lib/Modeler';
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import '@bpmn-io/properties-panel/assets/properties-panel.css'
// 引入属性面板模块
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from 'bpmn-js-properties-panel';
// 默认空流程 XML
const defaultXml = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL http://www.omg.org/spec/BPMN/2.0/20100524/bpmn0.xsd">
<bpmn:process id="Process_1" isExecutable="false">
<bpmn:startEvent id="StartEvent_1" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>`;
const BpmnModeler = () => {
const containerRef = useRef<HTMLDivElement>(null);
const panelRef = useRef<HTMLDivElement>(null);
const modelerRef = useRef<Modeler | null>(null);
// 存储当前 XML
const [xml, setXml] = useState<string>(defaultXml);
// 1. 初始化 BPMN 设计器
useEffect(() => {
if (!containerRef.current || !panelRef.current) return;
const modeler = new Modeler({
container: containerRef.current,
// 集成属性面板
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
],
propertiesPanel: {
parent: panelRef.current,
},
});
modelerRef.current = modeler;
// 加载默认 XML
modeler.importXML(defaultXml).catch((err) => {
console.error('加载失败', err);
});
// 监听修改事件
modeler.on('commandStack.changed', async () => {
try {
const { xml:string } = await modeler.saveXML({ format: true });
setXml(xml);
} catch (err) {
console.error('保存失败', err);
}
});
return () => {
modeler.destroy();
};
}, []);
// 2. 导出 XML 文件
const exportXml = async () => {
if (!modelerRef.current) return;
const { xml:string } = await modelerRef.current.saveXML({ format: true });
const blob = new Blob([xml], { type: 'application/xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'process.bpmn';
a.click();
URL.revokeObjectURL(url);
};
// 3. 导出 SVG 图片
const exportSvg = async () => {
if (!modelerRef.current) return;
const { svg } = await modelerRef.current.saveSVG();
const blob = new Blob([svg], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'process.svg';
a.click();
URL.revokeObjectURL(url);
};
return (
<div>
<h2>React 19 + TS + BPMN 设计器</h2>
{/* 操作按钮 */}
<div style={{ marginBottom: 10, gap: 10, display: 'flex' }}>
<button onClick={exportXml}>导出 BPMN XML</button>
<button onClick={exportSvg}>导出 SVG 图片</button>
</div>
{/* 画布 + 属性面板 布局 */}
<div style={{ display: 'flex', border: '1px solid #eee' }} >
{/* BPMN 画布 */}
<div ref={containerRef} style={{width:'calc(100% - 300px)'}} />
{/* 右侧属性面板 */}
<div
ref={panelRef}
style={{
width: '300px',
height: '600px',
borderLeft: '1px solid #eee',
}}
/>
</div>
</div>
);
};
export default BpmnModeler;
```
### 2. 在 App.tsx 中使用
```tsx
import BpmnViewer from './bpmn/components/demo/BpmnViewer';
import BpmnModeler from './bpmn/components/demo/BpmnModeler'
function App() {
return (
<div style={{ padding: 20 }}>
<BpmnModeler />
</div>
);
}
export default App;
```
---
## 六、运行效果
启动项目后,你会得到一个**完整可用的 BPMN 设计器**:
1. 左侧工具栏:可拖拽**开始/结束事件、用户任务、网关、连线**等
2. 中间画布:编辑流程图
3. 右侧面板:选中节点可**修改名称、ID、类型**等属性
4. 按钮:导出 `.bpmn` 文件、导出 `.svg` 图片
显示如下:

---
## 七、TS 类型补充(避免类型报错)
如果 TS 提示模块无类型定义,可在项目根目录创建 `types/bpmn.d.ts`:
```ts
declare module 'bpmn-js' {
export class Modeler {
constructor(options: any);
importXML(xml: string): Promise<any>;
saveXML(options?: any): Promise<{ xml: string }>;
saveSVG(options?: any): Promise<{ svg: string }>;
on(event: string, callback: () => void): void;
destroy(): void;
}
export default class Viewer {
constructor(options: any);
importXML(xml: string): Promise<any>;
destroy(): void;
}
}
declare module 'bpmn-js-properties-panel' {
export const BpmnPropertiesPanelModule: any;
export const BpmnPropertiesProviderModule: any;
}
```
然后在 `tsconfig.json` 中加入:
```json
"include": ["src", "types"]
```
---
## 八、常用功能扩展(企业级必备)
### 1. 加载本地 BPMN 文件
```tsx
// 文件上传加载
const loadLocalFile = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = async (ev) => {
const xml = ev.target?.result as string;
await modelerRef.current?.importXML(xml);
};
reader.readAsText(file);
};
```
### 2. 撤销 / 重做
```tsx
const undo = () => modelerRef.current?.get('commandStack').undo();
const redo = () => modelerRef.current?.get('commandStack').redo();
```
### 3. 清空画布
```tsx
const clearCanvas = () => modelerRef.current?.clear();
```
---
## 九、常见问题
1. **样式错乱**:必须引入 `bpmn-js` 自带的 CSS 文件
2. **属性面板不显示**:检查容器宽度、模块是否正确注册
3. **TS 类型报错**:使用上面的自定义类型声明
4. **React 19 兼容**:`bpmn-js` 不依赖 React 特性,**100% 兼容 React 19**
---
### 总结
1. 本教程基于 **React 19 + TS** 实现了**可用的 BPMN 设计器**,开箱即用
2. 核心分为 **Viewer(查看)** 和 **Modeler(编辑)**
3. 支持:拖拽节点、属性配置、导出 XML/SVG、实时预览
4. 可直接用于后台管理系统的**流程设计模块**
更多推荐

所有评论(0)