• bpmn-js 事件总线处理
  • 发布于 2个月前
  • 124 热度
    0 评论
bpmn-js中使用EventBus作为事件的处理句柄,EventBus的使用和我们常规使用的事件总线没啥大的区别,其源码位于:/diagram-js/lib/core/EventBus.js (bpmn-js使用diagram-js实现流程图的web端绘制呈现工具)。

EventBus使用
事件总线使用基本都是以监听、回调的方式来实现的。diagram-js提供的EventBus也不无例外。如下为EventBus使用方式。

1、添加监听事件
diagram-js提供的EventBus在监听方式上提供了几种不同的选择,如下,可根据需要选择不同的监听方式:
.普通监听
.带参监听
.返回值监听
.优先级监听
.上下文监听
 * // listen for event
 * eventBus.on('foo', function(event) {
 *
 *   // access event type
 *   event.type; // 'foo'
 *
 *   // stop propagation to other listeners
 *   event.stopPropagation();
 *
 *   // prevent event default
 *   event.preventDefault();
 * });
 *
 * // listen for event with custom payload
 * eventBus.on('bar', function(event, payload) {
 *   console.log(payload);
 * });
 *
 * // listen for event returning value
 * eventBus.on('foobar', function(event) {
 *
 *   // stop event propagation + prevent default
 *   return false;
 *
 *   // stop event propagation + return custom result
 *   return {
 *     complex: 'listening result'
 *   };
 * });
 *
 *
 * // listen with custom priority (default=1000, higher is better)
 * eventBus.on('priorityfoo', 1500, function(event) {
 *   console.log('invoked first!');
 * });
 *
 *
 * // listen for event and pass the context (`this`)
 * eventBus.on('foobar', function(event) {
 *   this.foo();
 * }, this);
2、发送事件
EventBus通过fire来发送事件,发送事件可配合上述不同类型监听实现。
 *
 * // false indicates that the default action
 * // was prevented by listeners
 * if (eventBus.fire('foo') === false) {
 *   console.log('default has been prevented!');
 * };
 *
 *
 * // custom args + return value listener
 * eventBus.on('sum', function(event, a, b) {
 *   return a + b;
 * });
 *
 * // you can pass custom arguments + retrieve result values.
 * var sum = eventBus.fire('sum', 1, 2);
 * console.log(sum); // 3

3、其他操作
off:移除监听回调,若回调函数为空,则移除该监听的所有回调
createEvent: 创建一个可被EventBus识别的事件
once:注册一个只能被监听一次的事件

如何使用eventbus?
我们可以通过bpmn-js获取的viewer/modeler对象在diagram-js加载完成后添加事件监听。通过bpmn-js提供的eventbus来进行事件监听可以帮助我们给流程编辑器添加钩子和流程图交互配置,如通过监听事件适当添加配置属性。

1、使用viewer进行监听
viewer可以在加载完成diagram-js加载完成后通过viewer.get('eventBus')获取eventbus。
var viewer = new BpmnJS({ container: bpmnContainer});

try {
    await viewer.importXML(diagramXM); // 此处异步操作完成后可进行事件操作
    var eventBus = viewer.get('eventBus');
    // you may hook into any of the following events
    var events = [
      'element.hover',
      'element.out',
      'element.click',
      'element.dblclick',
      'element.mousedown',
      'element.mouseup'
    ];

    events.forEach(function(event) {

  
      eventBus.on(event, function(e) {
        // e.element = the model element
        // e.gfx = the graphical element

        log(event, 'on', e.element.id);
      });
   });


} catch (err) {
console.error('Error happened: ', err);
}
可以通过off来取消监听,但需要改变下写法:
var viewer = new BpmnJS({ container: bpmnContainer});
 // 堆代码 duidaima.com
try {
    await viewer.importXML(diagramXM); // 此处异步操作完成后可进行事件操作
    var eventBus = viewer.get('eventBus');
    function ensureHoveringProcess(event) {
      event.element = rootElement;
      event.gfx = rootElementGfx;
    }
  eventBus.on('element.hover', ensureHoveringProcess)
  // 监听之后
   eventBus.off('element.hover', ensureHoveringProcess);
// 或者如下取消所有element.hover的监听
  eventBus.off('element.hover')


} catch (err) {
console.error('Error happened: ', err);
}
2、使用Modeler进行监听
modeler可以直接使用modeler对象进行监听和取消监听操作,而无需额外获取:
modeler.on('commandStack.changed', () => {
  // user modeled something or
  // performed an undo/redo operation
});

modeler.on('element.changed', (event) => {
  const element = event.element;

  // the element was changed by the user
});
3、依赖注入
bpmn-js提供给我们足够大的自定义空间,通过在modeler/viewer中的additionalModules配置让我们可以进行各类插件的自定义改装操作,可参照Bpmn-js自定义Palette:
const bpmnModeler = new BpmnModeler({
        container: this.$refs["bpmn-canvas"],
        additionalModules: [],

});
而自定义的additionalModules通过使用$inject属性来声明依赖注入的各个模块。如此我们也可以通过这种方式创建一个单独进行logger记录的插件:
 // logger插件
  function InteractionLogger(eventBus) {
    eventBus.on('element.hover', function(event) {
      console.log()
   })
 }
 
 InteractionLogger.$inject = [ 'eventBus' ]; // 注入插件模块
 
  // 插件模块声明
 var extensionModule = {
   __init__: [ 'interactionLogger' ],
  interactionLogger: [ 'type', InteractionLogger ]
};

// viewer加载
var bpmnViewer = new Viewer({
  container:viewerContainer, 
  additionalModules: [ extensionModule ] 
});
// modeler加载
var bpmnModeler = new BpmnModeler({
  container:viewerContainer, 
  additionalModules: [ extensionModule ] 
})
我们也可以通过自定义元素shape、palette时注入eventbus,添加我们自己的事件监听。

内置事件
通过diagram-js实现的元素绘制、布局相应的其会在内部内置元素的各类事件以提供我们调试,跟踪事件以及其他额外元素操作使用,在使用bpmn-js较为常见的事件监听如下:
1、元素事件类
element.changed,element.out,element.hover,element.updateId,element.marker.update,bpmnElement.added
2、copyPaste类
moddleCopy.canCopyProperties,moddleCopy.canSetCopiedProperty,copyPaste.canCopyElements,
copyPaste.elementsCopied,copyPaste.pasteElements,copyPaste.pasteElement,copyPaste.createTree,copyPaste.copyElement
3、contextPad类
contextPad.trigger,contextPad.open,contextPad.create,contextPad.close
4、render类
canvas.viewbox.changing,canvas.init,canvas.viewbox.changed,canvas.resized,render.shape,render.getShapePath,render.connection,render.getConnectionPath,canvas.destroy,diagram.init,diagram.destroy,diagram.clear
5、connect类
connection.added,connection.removed,connect.ended,connect.canceled
用户评论