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('禁止成环');
}
});