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教材》
系列相關推薦: