vue項目中如何使用有向無環圖(dag-diagram)
1、自定義右擊事件偶現問題
2、節點删除再添加反複操作幾次會出現,删除一個節點多個節點一起消失
3、檢測是否成環
關于有向無環圖在vue項目中的使用和安裝,已經有很多的文章有過介紹了,我在這就不再重複這些東西,本文主要介紹的是在使用dag-diagram(一下簡稱dag)這個插件時的小技巧或者說是一些經驗吧
<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) {
}
deep: true,
這樣就可以解決第一次點選節點時,自定義事件不出現的問題
問題原因:
在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],
});
這個功能我在看插件源碼的時候它是有寫這部分校驗的,但是不知道為什麼我在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;
if (item.src_node_id === dstNodeId) {
console.log(
'目标節點是',
item.src_node_id,
'次數為',
nth,
);
checkCircle(item.dst_node_id, ++nth); // eslint-disable-line
};
checkCircle(dst_node_id, 1);
if (isCircle) {
this.DataAll.edges.pop();
// alert('禁止成環');
this.$Message.error('禁止成環');