全網最詳bpmn.js教材-編輯、刪除節點篇

LinDaiDai_霖呆呆發表於2019-12-21

前言

Q: bpmn.js是什麼? ?️

bpmn.js是一個BPMN2.0渲染工具包和web建模器, 使得畫流程圖的功能在前端來完成.

Q: 我為什麼要寫該系列的教材? ?️

因為公司業務的需要因而要在專案中使用到bpmn.js,但是由於bpmn.js的開發者是國外友人, 因此國內對這方面的教材很少, 也沒有詳細的文件. 所以很多使用方式很多坑都得自己去找.在將其琢磨完之後, 決定寫一系列關於它的教材來幫助更多bpmn.js的使用者或者是期於找到一種好的繪製流程圖的開發者. 同時也是自己對其的一種鞏固.

由於是系列的文章, 所以更新的可能會比較頻繁, 您要是無意間刷到了且不是您所需要的還請諒解?.

不求贊?不求心❤️. 只希望能對你有一點小小的幫助.

編輯、刪除節點篇

雖然前面已經說了很多關於如何建立, 渲染元素的知識, 但是在實際使用上肯定不僅僅只侷限於建立TaskEvent這些節點上.

你可能還需要建立: 線(bpmn:SequenceFlow)、閘道器(ExclusiveGateway)、活動(Activities) 等等其他型別的節點.

甚至你想要在contextPad中定義一個刪除、編輯節點的功能.

那麼這一章節我們主要就是來講解這些.

通過閱讀你可以學習到:

contextPad上的刪除功能

讓我們接著上個章節的案例進行講解哈, 專案還是之前的專案LinDaiDai/bpmn-vue-custom

想要實現的功能是: 在contextPad中加上一個刪除功能(這裡加上一個小垃圾桶):

bpmnCustom20.png
bpmnCustom20.png

並且點選它的時候可以刪除當前的節點...

讓我們開啟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中的某個圖示獲取到當前節點的節點資訊然後做其他自定義的操作.

通過點選小圖示獲取節點資訊

bpmnCustom21.png
bpmnCustom21.png

如上圖, 先實現這個功能: 點選編輯圖示, 將節點資訊列印出來.

其實也很簡單, 經過了lindaidi-taskdelete之後, 我相信你也掌握了一些規律了.

反正要建立什麼圖示就往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中的資訊傳遞出去呢, 也就是我們在頁面上該怎麼拿到這個資訊呢?

比如我想實現: 點選上面?所說的編輯小圖示, 然後出現這麼一個彈窗, 顯示出節點的相關資訊:

bpmnCustom22.png
bpmnCustom22.png

(由於沒有引入任何的UI元件, 所以隨手寫了一些樣式)

哈哈?, 方法其實也有很多種:

  • 前端本地儲存localStorage
  • vuevuex
  • reactredux

以上技術都可以實現...

由於專案是用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相關的儲存. 然後在其中定義:

  1. nodeInfo<Object>: 用於儲存當前點選的節點的資訊
  2. 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.jsCustomContextPad.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教材》

系列相關推薦:

《全網最詳bpmn.js教材-基礎篇》

《全網最詳bpmn.js教材-http請求篇》

《全網最詳bpmn.js教材-事件篇》

《全網最詳bpmn.js教材-renderer篇》

《全網最詳bpmn.js教材-contextPad篇》

相關文章