Q: bpmn.js是什么? 🤔️javascript
”
bpmn.js是一个BPMN2.0渲染工具包和web建模器, 使得画流程图的功能在前端来完成.css
Q: 我为何要写该系列的教材? 🤔️前端
”
由于公司业务的须要于是要在项目中使用到bpmn.js
,可是因为bpmn.js
的开发者是国外友人, 所以国内对这方面的教材不多, 也没有详细的文档. 因此不少使用方式不少坑都得本身去找.在将其琢磨完以后, 决定写一系列关于它的教材来帮助更多bpmn.js
的使用者或者是期于找到一种好的绘制流程图的开发者. 同时也是本身对其的一种巩固.vue
因为是系列的文章, 因此更新的可能会比较频繁, 您要是无心间刷到了且不是您所须要的还请谅解😊.java
不求赞👍不求心❤️. 只但愿能对你有一点小小的帮助.node
虽然前面已经说了不少关于如何建立, 渲染元素的知识, 可是在实际使用上确定不只仅只局限于建立Task
、 Event
这些节点上.react
你可能还须要建立: 线(bpmn:SequenceFlow
)、网关(ExclusiveGateway
)、活动(Activities
) 等等其余类型的节点.git
甚至你想要在contextPad
中定义一个删除、编辑节点的功能.github
那么这一章节咱们主要就是来说解这些.web
经过阅读你能够学习到:
contextPad
上的删除功能让咱们接着上个章节的案例进行讲解哈, 项目仍是以前的项目LinDaiDai/bpmn-vue-custom
想要实现的功能是: 在contextPad
中加上一个删除功能(这里加上一个小垃圾桶):
而且点击它的时候能够删除当前的节点...
让咱们打开CustomContextPad.js
文件或者CustomContextPadProvider.js
文件, 而后在getContextPadEntries
方法中加上如下代码:
// CustomContextPad.js
getContextPadEntries(element) {
const { modeling } = this // modeling须要利用CustomContextPad.$inject注册进来
function removeElement(e) { // 点击的时候实现删除功能
modeling.removeElements([element])
}
function deleteElement() { // 建立垃圾桶
return {
group: 'edit',
className: 'icon-custom icon-custom-delete',
title: translate('删除'),
action: {
click: removeElement
}
}
}
return {
'append.lindaidai-task': {...},
'delete': deleteElement() // 返回值加上删除的功能
}
}
复制代码
能够看到要点就是:
modeling
引进来, 由于要使用到它的
removeElements
方法;
className
来实现修改默认样式的功能
OK👌, 接下来别忘了在咱们的app.css
中加上垃圾桶的样式:
/* app.css*/
.icon-custom-delete {
background-image: url('https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/delete.png');
}
.djs-context-pad .icon-custom-delete.entry:hover {
background: url('https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/delete.png') center no-repeat!important;
background-size: cover!important;
}
复制代码
(自定义modeler
中的CustomContextPadProvider.js
也是这么写的)
这样删除功能就实现了.
contextPad
上的编辑功能其实这里说的编辑功能, 是指在contextPad
上定一个编辑的图标, 而后点击的时候, 能够出现一个弹窗, 或者右边出现一个自定义的properties-panel
, 而后这里面能够显示出节点的一些信息.
这么作的缘由是:
properties-panel
, 而是将
properties-panel
做为一个抽屉隐藏在右侧, 点击
contextPad
中的某个图标才从右侧出来.
contextPad
中的某个图标获取到当前节点的节点信息而后作其余自定义的操做.
如上图, 先实现这个功能: 点击编辑图标, 将节点信息打印出来.
其实也很简单, 通过了lindaidi-task
和delete
以后, 我相信你也掌握了一些规律了.
反正要建立什么图标就往getContextPadEntries
的返回值加就能够了:
// CustomContextPad.js
getContextPadEntries(element) {
function clickElement(e) {
console.log(element)
}
function editElement() { // 建立编辑图标
return {
group: 'edit',
className: 'icon-custom icon-custom-edit',
title: translate('编辑'),
action: {
click: clickElement
}
}
}
return {
'append.lindaidai-task': {...},
'edit': editElement(), // 返回值加上编辑功能
'delete': deleteElement() // 返回值加上删除的功能
}
}
复制代码
而后记得在app.css
中加上.icon-custom-edit
的样式, 这里就不贴代码了.
其实咱们会发现, 经过点击小图标获取到节点信息很容易就实现了, 可是如何将在CustomContextPad.js
中的信息传递出去呢, 也就是咱们在页面上该怎么拿到这个信息呢?
好比我想实现: 点击上面👆所说的编辑小图标, 而后出现这么一个弹窗, 显示出节点的相关信息:
(因为没有引入任何的UI
组件, 因此随手写了一些样式)
哈哈😄, 方法其实也有不少种:
localStorage
vue
的
vuex
react
的
redux
以上技术均可以实现...
因为项目是用vue
开发的, 因此这里我就演示一下利用vuex
来进行交互😄.
首先在咱们的项目里安装上vuex
:
$ npm i vuex --save-D
复制代码
而后在src
目录下建立好一个store
文件夹用来存放它, 并记得在main.js
用进行引用:
// main.js
import store from './store'
...
new Vue({
...
store,
render: h => h(App),
}).$mount('#app')
复制代码
让咱们在store
中建立一个叫作bpmn
模块, 专门用来定义bpmn
相关的存储. 而后在其中定义:
nodeInfo<Object>
: 用于存储当前点击的节点的信息
nodeVisible<Boolean>
: 用于判断弹窗显示隐藏的变量
// store/modules/bpmn.js
const bpmn = {
state: {
nodeVisible: false,
nodeInfo: {}
},
mutations: {
TOGGLENODEVISIBLE: (state, visible) => {
state.nodeVisible = visible
},
SETNODEINFO: (state, info) => {
state.nodeInfo = info
}
},
actions: {}
}
export default bpmn
复制代码
定义好这些以后, 咱们就能够在CustomContextPadProvider.js
里的clickElement
作文章了:
// CustomContextPadProvider.js
import store from '../../../store' // 引入store
function clickElement(e) {
console.log(element)
store.commit('SETNODEINFO', element) // 存储节点信息
store.commit('TOGGLENODEVISIBLE', true)
}
复制代码
因为CustomContextPadProvider.js
和CustomContextPad.js
的作法都是同样的, 这里我就以CustomContextPadProvider.js
为案例进行讲解.
经过以上的步骤, 已经能够将这两个值存储到store
中了, 接下来只是看看页面上该如何调用它们.
让咱们打开custom-modeler.vue
文件, 给里面加个小弹窗:
<template>
<div class="modal" v-if="bpmnNodeVisible" @click="close">
<div class="modal-content">
<div class="modal-ctx">
<div class="modal-item">
节点id: {{ bpmnNodeInfo.id }}
</div>
<div class="modal-item">
节点type: {{ bpmnNodeInfo.type }}
</div>
</div>
</div>
</div>
</template>
复制代码
弹窗样式随便写了点, 在项目代码里能够看到, 这里就不贴了.
而后编辑相关的js
代码:
<script> import { mapState, mapMutations } from 'vuex' export default { ... // 这个省略号是省略代码 methods: { // 方法 ...mapMutations(['TOGGLENODEVISIBLE']), // 这个省略号是解构 close () { this.TOGGLENODEVISIBLE(false) } }, computed: { // 计算属性 ...mapState({ // 解构 bpmnNodeInfo: state => state.bpmn.nodeInfo, bpmnNodeVisible: state => state.bpmn.nodeVisible }) } } </script>
复制代码
完成了上面的步骤以后, 咱们就实现了点击contextPad
中的编辑图标, 出现显示节点相关信息的小弹窗, 点击阴影出关闭小弹窗的功能了, 固然了你也能够在关闭的时候, 清空掉store
中的节点信息nodeInfo
, 这里就不作这些操做了.
最后让咱们来梳理一下, 前面的关键步骤:
vuex
来实现跨组件传递数据;
store
中;
vue
中计算属性可以监听
state
的改变的原理来更新你的
UI
(也就是出现弹窗)
(我开始是想用最简单的localStorage
来实现的, 后来发现computed
不可以监听到它的改变, 致使localStorage
中的nodeVisible
虽然已经变化了, 可是bpmnNodeVisible
仍是没有. 所以后来转用了vuex
)
其实这一章节主要是给你们传递一种思路, 如何将contextPad
与你的页面结合起来, 讲解中只是说了一种最简单的出现小弹窗的状况, 可能在实际开发中你会有更多复杂的需求, 复杂的交互.
不过也很高兴能给你提供一个这样的解决方案, 也能够说给你一点灵感吧😊...
由于本身在研究bpmn.js
的时候, 也是没有任何人指导, 全靠本身查看官方案例还有绞尽脑汁的想, 因此我才明白这玩意的麻烦... 哈哈哈😂, 扯多了, 这一章节就到这里吧.
上面👆案例用的都是同一个项目🦐
项目案例Git地址: LinDaiDai/bpmn-vue-custom 喜欢的小伙伴请给个Star
🌟呀, 谢谢😊
系列所有目录请查看此处: 《全网最详bpmn.js教材》
系列相关推荐: