全網最詳bpmn.js教材-properties篇

前言

Q: bpmn.js是什麼? 🤔️javascript

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

Q: 我爲何要寫該系列的教材? 🤔️前端

由於公司業務的須要於是要在項目中使用到bpmn.js,可是因爲bpmn.js的開發者是國外友人, 所以國內對這方面的教材不多, 也沒有詳細的文檔. 因此不少使用方式不少坑都得本身去找.在將其琢磨完以後, 決定寫一系列關於它的教材來幫助更多bpmn.js的使用者或者是期於找到一種好的繪製流程圖的開發者. 同時也是本身對其的一種鞏固.java

因爲是系列的文章, 因此更新的可能會比較頻繁, 您要是無心間刷到了且不是您所須要的還請諒解😊.git

不求贊👍不求心❤️. 只但願能對你有一點小小的幫助.github

Properties篇

哈哈 來了 來了 它終於來了😂.web

讓你們久等的Properties篇🎉.npm

其實霖呆呆工做上用到的bpmn.js的內容也就只侷限於以前寫的文章了, 算是將實際用到的知識全盤脫出了... 那麼就有人會好奇的問了...爲何連Properties-panel這樣重要的功能都沒有用到呢🤔️?json

這其實和咱們團隊的用法有關:canvas

最開始接觸使用到bpmn.js是由於須要用它來繪製工做流實現決策引擎的這麼一個功能. 而咱們的作法是前端經過bpmn.js來繪製流程圖, 圖中的StartUserTaskBusinessRuleTask等等我在這裏都稱之爲節點. 每一個節點都對應着xml文件中的標籤, 傳統的作法多是將各個節點的屬性都保存到標籤上, 例如我這裏有一個開始節點的xml標籤:

<startEvent id="StartEvent_1y45yut" name="開始" roles="admin"></startEvent>
複製代碼

而後給這個節點增長上一個名爲「權限(roles)」的自定義屬性, 這個屬性會保存在xml中, 而且導出這個文件的時候也會留在上面.

咱們雖然每一個節點也都會關聯不少信息, 可是這些信息並非直接保存在xml 標籤裏的. 而是每一個節點都會有一個 id , 後臺有一個表專門用於存放每一個節點的附加信息, 因此每次點擊節點的時候, 都經過這個id來調取後臺存儲的數據, 從而拿到節點對應的屬性, 右邊出現一個抽屜將這些屬性信息顯示在裏面能夠進行修改. 修改保存以後, 也是調用後臺的接口來修改表裏的信息. 因此主要的邏輯仍是集中在後臺上. 所以對於xml的操做還真不是太多, 天然的也就沒用上Properties-panel了.

可是個人這種作法, 你也能夠理解爲右邊出現的「抽屜」 就是我自定義的Properties-panel, 由於它確實也起到了與節點關聯屬性的做用.

OK, 言歸正傳啦, 雖然我工做中並無用到它, 可是通過讀者給出的意見以及本身對它的一些研究, 仍是能用它作一些業務實現的, 但願在你認真看完以後能有所收穫😁.

經過這一章節的閱讀你能夠學習到:

  • 什麼是 bpmn properties🤔️?
  • 如何讀取 bpmn properties🤔️?
  • 如何修改 bpmn properties🤔️?
  • 使用 updateProperties方法🤔️?

bpmn properties屬性介紹以及基本用法

1. 什麼是bpmn properties🤔️?

讓咱們先來搞懂一下什麼是bpmn properties🤔️?

咱們在用bpmn.js畫的每個節點其實都被稱之爲diagram element(圖表元素, 是否是很好理解😁)

而在bpmn文件中的每一個xml標籤稱之爲BPMN element.

diagram elementBPMN element的一些屬性關聯起來靠的是一個叫作businessObject的屬性. 從名稱上理解你也能夠知道它是一個對象(Object), 你能夠在這個對象中添加上一些特殊的屬性, 而且這些屬性是能夠直接插到BPMN element上的.

舉個例子🌰:

我繪製了一個StartEvent節點, 它對應的:

  • diagram element:

    {
    	id: "StartEvent_1y45yut",
    	type: "bpmn:StartEvent",
    	businessObject: {
    		$type: "bpmn:StartEvent",
    		name: "開始"
    	}
    }
    複製代碼
  • BPMN element:

    <startEvent id="StartEvent_1y45yut" name="開始"></startEvent>
    複製代碼

像這類屬性就是bpmn properties, 你能夠用它來實現你的業務須要.

2. 如何讀取bpmn properties🤔️?

不知道你們是否還記得我在《事件篇》中用到的一段代碼:

addModelerListener () {
       // 監聽 modeler
      const bpmnjs = this.bpmnModeler
      const that = this
      const events = ['shape.added', 'shape.move.end', 'shape.removed']
      events.forEach(function(event) {
        that.bpmnModeler.on(event, e => {
          var elementRegistry = bpmnjs.get('elementRegistry')
          var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
          if (event === 'shape.added') {
            console.log('新增了shape')
          } else if (event === 'shape.move.end') {
            console.log('移動了shape')
          } else if (event === 'shape.removed') {
            console.log('刪除了shape')
          }
        })
      })
    }
複製代碼

這個方法是放在 將字符串轉換成圖顯示出來 以後, 用於給元素綁定事件.

其中就有用到elementRegistry.

因此若是是在html中, 你就能夠用這種方式來獲取bpmn properties:

<body>
  <div id="canvas"></div>
<script> var bpmnJS = new BpmnJS({ container: '#canvas' }); bpmnJS.importXML(xmlStr, function(err) { if (!err) { var elementRegistry = bpmnJs.get('elementRegistry') var startEventElement = elementRegistry.get('StartEvent_1y45yut'), startEvent = startEventElement.businessObject; console.log(startEvent.name) // 開始 } } </script>
複製代碼

而在一些class裏, 好比CustomRenderer.js裏, 你能夠直接用.的方式就獲取到了:

export default class CustomRenderer extends BaseRenderer {
	drawShape (parentNode, element) {
		// element.businessObject
		// or 解構
		// const { businessObject } = element
	}
}
複製代碼

3. 如何修改bpmn properties🤔️?

你在bpmn文件中, 可能會看到這樣一段代碼:

<bpmn:sequenceFlow id="SequenceFlow_1" sourceRef="StartEvent_1" targetRef="Task_1" name="FOO &gt; BAR?">
      <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression"><![CDATA[${foo > bar}]]></bpmn:conditionExpression>
    </bpmn:sequenceFlow>
複製代碼

裏面的xsi:typesourceRef這些屬性是啥啊🤔️? 我怎麼知道哪類標籤有哪些屬性🤔️?

你其實能夠在官方給的這個bpmn.json中查找到:

《meta-model descriptor》

設置的話能夠根據如下方法:

var moddle = bpmnJS.get('moddle');

// 建立一個BPMN element , 而且載入到導出的xml裏 var newCondition = moddle.create('bpmn:FormalExpression', { body: '${ value > 100 }' });

複製代碼// 寫入屬性, 可是不支持撤銷 sequenceFlow.conditionExpression = newCondition; 複製代碼

上面👆的這種方式是不支持撤銷的, 若是你想要可以 撤銷/從新 的話, 你能夠經過如下這種方式:

var modeling = bpmnJS.get('modeling'); 複製代碼modeling.updateProperties(sequenceFlowElement, { conditionExpression: newCondition }); 複製代碼

也就是經過modeling.updateProperties()這個方法.

這個modeling好像是須要引入的, 反正若是我是使用DNS 遠程的引入下面的這個js好像就會報錯Uncaught Error: No provider for "modeling"!.

<script src="https://unpkg.com/bpmn-js@6.0.2/dist/bpmn-viewer.development.js"></script>
複製代碼

固然若是你是使用npm 下載的話就沒有這個問題了.

這個方法的第一個參數是一個 diagram element, 也就是前面咱們提到的用elementRegistry獲取到的對象.

第二個參數是要修改的屬性, 它是一個Map結構.

4. 使用updateProperties方法

例如🌰, 我想在點擊某個類型爲bpmn:Task的節點的時候, 修改它的name屬性, 我能夠這麼作:

  • 給節點添加點擊事件
  • 判斷節點類型爲 bpmn:Task , 只對這種類型的節點作後續處理
  • 使用 updateProperties更新 name
createNewDiagram () {
        // 將字符串轉換成圖顯示出來
        this.bpmnModeler.importXML(xmlStr, (err) => {
            if (err) {
                // console.error(err)
            } else {
                // 這裏是成功以後的回調, 能夠在這裏作一系列事情
                this.success()
            }
        })
    },
    success () {
        this.addModelerListener() // 添加監聽事件
    },
    addModelerListener () {
    		const eventBus = this.bpmnModeler.get('eventBus')
      	const modeling = this.bpmnModeler.get('modeling')
      	const elementRegistry = this.bpmnModeler.get('elementRegistry');
      	const eventTypes = ['element.click', 'element.changed'];
      	eventTypes.forEach(function(eventType) {
          	eventBus.on(eventType, function (e) {
              	if (!e || !e.element) {
                  console.log('無效的e', e)
                  return
                }
              	if (eventType === 'element.click') {
                  console.log('點擊了element', e)
                  var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
                  if (shape.type === 'bpmn:Task') {
                    modeling.updateProperties(shape, {
                    	name: '我是修改後的Task名稱'
                  	})
                  }
                }
            })
        })
    }
複製代碼

固然你也能夠一次性修改多個屬性:

modeling.updateProperties(startEventElement, {
	name: '我是修改後的虛線節點',
	isInterrupting: false
})
複製代碼

我經過查找前面的 meta-model descriptor 知道StartEvent還有一個isInterrupting屬性, 因而試着修改它, 結果居然成功了, 將開始節點變爲了虛線爲邊框的節點:

bpmnModeler5.png
bpmnModeler5.png

固然你也能夠加一些除了meta-model descriptor裏的一些自定義屬性:

modeling.updateProperties(shape, {
	name: '我是修改後的虛線節點',
	isInterrupting: false,
	customText: '我是自定義的text屬性'
})
複製代碼

只不過, 它們會被放到$attrs中:

bpmnModeler6.png
bpmnModeler6.png

而且這種方式, 也是能夠直接修改到bpmn文件中的:

bpmnModeler7.png
bpmnModeler7.png

後語

這一章節主要是向你們介紹了一下bpmn properties的概念以及操做方式...其實在這以前, 我甚至不知道怎麼給xml標籤上添加屬性, 也甚至不知道updateProperties怎麼使用😂...

還好皮厚的我不恥下問, 在羣裏問了一些小夥伴...

哈哈哈, 手動艾特感謝 @網易-付超老哥 還有@李岱老哥 , 在研究bpmn.js屬性上面給個人幫助, 固然我也知道不少小夥伴但願我能快點更上一篇關於properties-panel的內容...

但今天真的有點累了... 容我先緩一緩, 咱明天再更行不😁.

(嗯...不行也得行, 我說了算...)

最後, 若是你也對bpmn.js 感興趣能夠掃碼進咱們的交流羣👇👇👇, 共同窗習, 共同進步.

最最後, 喜歡霖呆呆的小夥伴能夠關注個人公衆號呀, 我會不按期的更新一些前端方面的知識, 另外單身的小哥哥小姐姐也有福利呀嘻嘻嘻嘻😁

LinDaiDai公衆號二維碼.jpg
LinDaiDai公衆號二維碼.jpg
相關文章
相關標籤/搜索