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