vue项目中如何使用有向无环图?dag-diagram

vue项目中如何使用有向无环图(dag-diagram)

1、自定义右击事件偶现问题

2、节点删除再添加反复操作几次会出现,删除一个节点多个节点一起消失

3、检测是否成环

关于有向无环图在vue项目中的使用和安装,已经有很多的文章有过介绍了,我在这就不再重复这些东西,本文主要介绍的是在使用dag-diagram(一下简称dag)这个插件时的小技巧或者说是一些经验吧

1、自定义右击事件偶现问题

<DAGBoard

:data-all="DataAll"

@updateDAG="updateDAG"

@editNodeDetails="editNodeDetails"

@doSthPersonal="doSthPersonal"

/>

插件中有一个doSthPersonal事件,就是用来自定义右击事件的,可以在这个事件中写你所要自定义的右击事件的代码,

但是有一个前提是你需要在每个节点的rightClickEvent中添加这个自定义事件的eventName和label

下面的代码是dag插件中的源码:

const rightClickEvent = this.DataAll.nodes[i].rightClickEvent || null

1

因此我们可以在自己的项目的updateDAG事件中这样写

this.DataAll.nodes[i].rightClickEvent = [

{

label: 'CREATE NODE',

eventName: 'creatednode',

},

{

label: 'DELETE NODE INFO',

eventName: 'deletenode',

},

];

如果只是简单的这样写上的话你会发现,自定义事件在你第一次去右击的时候是不会出来的,但是第二次就会有了,这是因为updateDAG方法只有节点在幕布内发生变化时(移动或删除)才会执行,在将节点拖入到幕布中的这一事件中是不会触发的

所以我使用了watch来监听this.DataAll.nodes的长度,来添加自定义事件,因为nodes的长度在节点被拖入幕布的时候就会发生变化

'DataAll.nodes.length': {

handler() {

for (let i = 0; i < this.DataAll.nodes.length; i += 1) {

this.DataAll.nodes[i].rightClickEvent = [

{

label: 'CREATE NODE',

eventName: 'creatednode',

},

{

label: 'DELETE NODE INFO',

eventName: 'deletenode',

},

];

}

},

deep: true,

},

这样就可以解决第一次点击节点时,自定义事件不出现的问题

2、节点删除再添加反复操作几次会出现,删除一个节点多个节点一起消失

问题原因:

在dag插件中,每个节点的id都是由this.DataAll.nodes.length + 100组成的,如果你是删除节点的时候是先删除的最后添加的节点,那没问题,但是如果删除的是非最后一个节点,那就会出现新添加的节点id和已存在的节点id重复的问题,所以当你移动新添加的节点或者删除新添加的节点时,会有另一个节点随之消失

解决方法:

所以在给节点id赋值时我们应该添加一种情况

就是当用户执行删除操作后,应该将id的值设置为最后添加的id值+1+100,这样就不会出现有重复id的情况

if (this.DataAll.nodes.length) {

id1 = this.DataAll.nodes[len - 1].id + 1 - 100 + 100;

} else {

id1 = this.DataAll.nodes.length + 100;

}

this.DataAll.nodes.push({

...params.desp,

id: id1,

in_ports: [0, 1, 2, 3, 4],

out_ports: [0, 1, 2, 3, 4],

});

3、检测是否成环

这个功能我在看插件源码的时候它是有写这部分校验的,但是不知道为什么我在dag这个项目中数据成环后并没有提示,在我自己的项目中也并未实现改功能

于是我就把插件中的关于检测是否成环这部分代码拿出来,直接写在了我自己的 项目中

其实用的还是插件中的源码

// 检测是否成环

this.DataAll.edges.forEach((item) => {

let isCircle = false;

// 出口 入口id

const { dst_node_id } = item; // eslint-disable-line

const checkCircle = (dstNodeId, nth) => {

if (nth > this.DataAll.nodes.length) {

isCircle = true;

return false;

}

this.DataAll.edges.forEach((item) => {

if (item.src_node_id === dstNodeId) {

console.log(

'目标节点是',

item.src_node_id,

'次数为',

nth,

);

checkCircle(item.dst_node_id, ++nth); // eslint-disable-line

}

});

return false;

};

checkCircle(dst_node_id, 1);

if (isCircle) {

this.DataAll.edges.pop();

// alert('禁止成环');

this.$Message.error('禁止成环');

}

});