Q: bpmn.js是什么? 🤔️javascript
bpmn.js是一个BPMN2.0渲染工具包和web建模器, 使得画流程图的功能在前端来完成.前端
Q: 我为何要写该系列的教材? 🤔️vue
由于公司业务的须要于是要在项目中使用到bpmn.js
,可是因为bpmn.js
的开发者是国外友人, 所以国内对这方面的教材不多, 也没有详细的文档. 因此不少使用方式不少坑都得本身去找.在将其琢磨完以后, 决定写一系列关于它的教材来帮助更多bpmn.js
的使用者或者是期于找到一种好的绘制流程图的开发者. 同时也是本身对其的一种巩固.java
因为是系列的文章, 因此更新的可能会比较频繁, 您要是无心间刷到了且不是您所须要的还请谅解😊.ios
不求赞👍不求心❤️. 只但愿能对你有一点小小的帮助.git
上一章节咱们介绍了bpmn.js
的一些基础知识点以及介绍了在vue
是如何使用的, 要是对bpmn.js
不了解的小伙请移步:github
这一章节主要讲解的是关于bpmn.js
如何与后台进行交互的问题, 经过学习此章节你能够学习到:web
将编辑以后的最新bpmn发送给后台canvas
在以前的案例中使用的一直都是本地写死的一个xml
字符串, 那么实际使用上确定不会以这种方式.
咱们团队如今采用的作法是:
bpmn
文件的地址axios
请求这个地址获得xml
的字符串(这里命名为bpmnXmlStr
)importXML
方法将字符串转化为图形并渲染.为了模拟上面的执行环境我接着上一章节的项目案例bpmn-vue-basic在components文件夹下建立一个axios.vue
的 文件并配置好路由:
const routes = [
...
{
path: '/axios',
component: () => import('./../components/axios')
}
]
复制代码
同时在项目中安装axios
以用于前端发送http
请求:
npm i axios --save-D
复制代码
首先在HTML
代码中做出一个loading
的效果, 用户前端在获取到xml
以前的一个展现:
// axios.vue
<template>
<div class="containers">
<div class="loading" v-if="loading">
Loading...
</div>
<template v-else>
<div class="canvas" ref="canvas"></div>
<div id="js-properties-panel" class="panel"></div>
</template>
</div>
</template>
复制代码
而后在js
中引入axios
并定义一个getXmlUrl
方法模拟获取bpmn
文件地址:
// axios.vue
<script>
...
import axios from 'axios'
import { xmlStr } from '../mock/xmlStr' // 引入一个本地的xml字符串, 如果没有获取到后台的数据则用它
export default {
...
data () {
return {
...
loading: true,
xmlUrl: '',
defaultXmlStr: xmlStr
}
},
methods: {
async init () {
this.loading = true
this.xmlUrl = await this.getXmlUrl()
console.log(this.xmlUrl)
this.loading = false
this.$nextTick(() => { // 等待 DOM 更新以后再对工做流进行初始化
this.initBpmn()
})
},
getXmlUrl () { // 该方法模拟请求后台获取bpmn文件地址
return new Promise(resolve => {
setTimeout(() => {
const url = 'https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bpmn' // 模拟网络请求的一个地址
resolve(url)
}, 1000)
})
},
initBpmn () {
... // 这里是初始化工做流的代码
this.createNewDiagram()
},
async createNewDiagram () {
const that = this
let bpmnXmlStr = ''
if (this.xmlUrl === '') { // 如果后台没有数据则使用默认的一个xml
bpmnXmlStr = this.defaultXmlStr
this.transformCanvas(bpmnXmlStr)
} else {
let res = await axios({
method: 'get',
timeout: 120000,
url: that.xmlUrl,
headers: { 'Content-Type': 'multipart/form-data' }
})
console.log(res)
bpmnXmlStr = res['data']
this.transformCanvas(bpmnXmlStr)
}
},
transformCanvas(bpmnXmlStr) {
// 将字符串转换成图显示出来
this.bpmnModeler.importXML(bpmnXmlStr, (err) => {
if (err) {
console.error(err)
} else {
this.success()
}
// 让图能自适应屏幕
var canvas = this.bpmnModeler.get('canvas')
canvas.zoom('fit-viewport')
})
},
success () {
console.log('建立成功!')
}
}
}
</script>
复制代码
你能够直接用我在案例中模拟获取地址的那个路径:
hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/bpmnMock.bp…
案例Git地址: LinDaiDai-bpmn.js测试案例axios.vue
上面咱们介绍了如何从后台那里拿到数据并渲染到页面上, 但这样是不够的.
可能你须要将编辑以后的最新bpmn
存储到后台.
该功能就涉及到了bpmn.js
中的事件绑定, 也就是前端须要给图形绑定一个事件来检测到图形的改变, 并获取到最新的xml
信息.
新建一个save.vue
文件并将axios.vue
里的内容复制进来.
在success()
方法中添加一个addBpmnListener()
绑定事件的方法:
// save.vue
<script>
success () {
console.log('建立成功!')
this.addBpmnListener()
},
// 添加绑定事件
addBpmnListener () {
const that = this
// 给图绑定事件,当图有发生改变就会触发这个事件
this.bpmnModeler.on('commandStack.changed', function () {
that.saveDiagram(function(err, xml) {
console.log(xml) // 这里获取到的就是最新的xml信息
})
})
},
// 下载为bpmn格式,done是个函数,调用的时候传入的
saveDiagram(done) {
// 把传入的done再传给bpmn原型的saveXML函数调用
this.bpmnModeler.saveXML({ format: true }, function(err, xml) {
done(err, xml)
})
}
</script>
复制代码
如图所示:
案例Git地址: LinDaiDai-bpmn.js测试案例save.vue
在上面咱们监听commandStack.changed
事件就能实时获取到最新的xml
信息.
拿到这些信息以后你能够选择在每次图形改变的时候就请求给后台传递给他们最新的xml
;
也能够选择将其保存到一个变量中, 而后在页面中给一个保存按钮, 当点击按钮的时候再传递给后台.
或许你可能彻底不须要再请求给后台, 而是但愿本地就可以下载为bpmn
文件或者svg
文件.
在上面save.vue
案例的基础上增长两个保存按钮:
而后修改HTML
代码:
// save.vue
<template>
...
<ul class="buttons">
<li>
<a ref="saveDiagram" href="javascript:" title="保存为bpmn">保存为bpmn</a>
</li>
<li>
<a ref="saveSvg" href="javascript:" title="保存为svg">保存为svg</a>
</li>
</ul>
</template>
复制代码
在js
代码中加上:
// save.vue
<script>
...
addBpmnListener () {
const that = this
// 获取a标签dom节点
const downloadLink = this.$refs.saveDiagram
const downloadSvgLink = this.$refs.saveSvg
// 给图绑定事件,当图有发生改变就会触发这个事件
this.bpmnModeler.on('commandStack.changed', function () {
that.saveSVG(function(err, svg) {
that.setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg)
})
that.saveDiagram(function(err, xml) {
that.setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml)
})
})
},
// 下载为SVG格式,done是个函数,调用的时候传入的
saveSVG(done) {
// 把传入的done再传给bpmn原型的saveSVG函数调用
this.bpmnModeler.saveSVG(done)
},
// 下载为bpmn格式,done是个函数,调用的时候传入的
saveDiagram(done) {
// 把传入的done再传给bpmn原型的saveXML函数调用
this.bpmnModeler.saveXML({ format: true }, function(err, xml) {
done(err, xml)
})
},
// 当图发生改变的时候会调用这个函数,这个data就是图的xml
setEncoded(link, name, data) {
// 把xml转换为URI,下载要用到的
const encodedData = encodeURIComponent(data)
// 下载图的具体操做,改变a的属性,className令a标签可点击,href令能下载,download是下载的文件的名字
console.log(link, name, data)
let xmlFile = new File([data], 'test.bpmn')
console.log(xmlFile)
if (data) {
link.className = 'active'
link.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
link.download = name
}
}
</script>
复制代码
案例Git地址: LinDaiDai-bpmn.js测试案例save.vue
系列相关推荐