vue项目中使用bpmn-流程图xml文件中节点属性转json结构
内容概述
本系列“vue项目中使用bpmn-xxxx”分为七篇,均为自己使用过程中用到的实例,手工原创,目前陆续更新中。主要包括vue项目中bpmn使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。如果转载或通过爬虫直接爬的,格式特别丑,请来原创看:我是作者原文
前情提要
前面我们讨论了bpmn流程图的基本绘制、添加节点颜色等,本次我们来说,如何把xml文件中各种标签包裹的节点属性,转成前端常用的json格式,方便回显在页面。首先,我们通过一张图看一下流程图xml文件中,节点的属性有哪几种格式。
思路分析
可以看到,节点的属性被包含在<bpmn:extensionElements>下的<camunda:inputOutput>标签下,下一层的每个 <camunda:inputParameter>都是一个属性,属性共分为三总格式
- <camunda:inputParameter>标签下没有子元素
它的属性“name”便是节点的属性名,标签中值“少年的你”便是节点属性值。所以我们得到的第一个属性为“selfName:少年的你“ - <camunda:inputParameter>下有子元素
2.1 子元素为<camunda:map>,map在后端语言里相当于前端的对象(object),对,没有错,这个<camunda:map>标签表示的就是对象。它的下一级标签<camunda:entry>表示对象下的各个键值对。key是键名,标签值是属性值。所以,根据<camunda:map>标签,我们得到节点的第二个属性:nodeDesc: { class: '一年一班',age: '8'},看来这个节点是个刚上一年级的8岁小朋友。
2.2 子元素为<camunda:list>,根据2.1的判断,聪明的你可能猜到了,list表示的是数组。数组没有键值对,所以它下面的<camunda:value>表示数组的其中一 项。所以,我们得到节点的第三个属性:interestFood: ['苹果', '香蕉', '西瓜']。所以,根据这一段xml,我们希望的是,能把它解析成一段前端js读懂的json数据,例如:
- <camunda:inputParameter>标签下没有子元素
form:{ selfName:少年的你, nodeDesc: { class: '一年一班', age: '8' }, interestFood: ['苹果', '香蕉', '西瓜'] }
有了这段json,我们就可以将节点属性以想要的形式,展示在流程图的外面了。那么,开动吧~~~
代码实现
注意,虽然流程图文件是一段xml文件,但是我们不采用直接读xml文件的方式去解析,因为bpmn的element下,为我们提供了“businessObject“,这是个万能的小可爱,它里面包含节点的所有信息。那么怎样拿到节点实例element呢,在第二篇中,我们讲到拿到节点实例有两种方式,1是点击事件获取,2是根据id。此时我们采取第一种,即当点击每个节点时,我们可以拿到e,e.element.businessObject 就是我们想要。
addEventBusListener() { let eventBus = this.bpmnModeler.get('eventBus'); // 注册节点事件,eventTypes中可以写多个事件 let eventTypes = ['element.click']; eventTypes.forEach((eventType) => { eventBus.on(eventType, (e) => { let {element} = e; if (!element.parent) return; if (!e || element.type === 'bpmn:Process') { return false; } else { if (eventType === 'element.click') { let businessObject = element.businessObject || element; // 此时的businessObject 是我们想要的万能的小可爱 this.splitBusiness2Json(businessObject); } } }); }); }
拿到businessObject,接下来我们要去拆分它,将属性转成json。根据上面的分析,我们已经知道了属性的三种形式,那么直接上代码吧,splitBusiness2Json是主要方法:
splitBusiness2Json(businessObject) { let formData = {}; let params = this.getExtensionElement(businessObject, 'camunda:InputOutput'); if (params && params.inputParameters) { params.inputParameters.forEach((item) => { let definition = item.definition; if (definition) { if (definition.$type === 'camunda:List') { let arr = []; definition.items.forEach((itemsItem) => { arr.push(itemsItem.value); }); formData[item.name] = arr; } else if (definition.$type === 'camunda:Map') { let obj = {}; if (definition.entries) { definition.entries.forEach((entriesItem) => { obj[entriesItem.key] = entriesItem.value; }); formData[item.name] = obj; } } } else { formData[item.name] = item.value; } }); } this.form = formData; console.log('this.form', this.form); }
getExtensionElement:获取extensionElement下所有的属性
getExtensionElement(element, type) { if (!element.extensionElements) { return; } return element.extensionElements.values.filter((extensionElement) => { return extensionElement.$instanceOf(type); })[0]; }
成果验证
此时,我打印一下this.form,格式如下:
bingo~格式和我们开篇时分析的完全相同,说明我们的函数成功了。此时可以把属性显示在需要的地方了。
我猜,此时你肯定有一个想法,既然属性可以转成json展示, 那如果在上图的表单里对属性进行修改,可以将修改得值写回到xml中,保存到后端吗?当然可以,下一篇,我们来说json转换为流程图xml。
进行到现在,我们已经实现了将xml中的属性转化为json了,完整代码是个文件夹,不知道怎样传到博客里。所以,想要获取完整代码的小伙伴, 可以公粽号联系我,扫下面二维码或公众号搜“前端便利贴”,即可获取~