全网最详bpmn.js教材-编辑、删除节点篇

前言

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

并且点击它的时候可以删除当前的节点...

让我们打开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

如上图, 先实现这个功能: 点击编辑图标, 将节点信息打印出来.

其实也很简单, 经过了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

(由于没有引入任何的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篇》

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容