流程圖控件GoJS教程:變更事件
GoJS是一款功能強(qiáng)大,快速且輕量級(jí)的流程圖控件,可幫助你在JavaScript 和HTML5 Canvas程序中創(chuàng)建流程圖,且極大地簡(jiǎn)化您的JavaScript / Canvas 程序。
GoJS現(xiàn)已更新至最新版本2.0.16發(fā)布,修復(fù)了一些bug,增強(qiáng)用戶(hù)體驗(yàn),趕快下載試試吧~
變更事件
GoJS生成 三種基本類(lèi)型的事件: DiagramEvent,InputEvent和ChangedEvent。本頁(yè)討論后者,它們是在修改Diagram,GraphObject, Model或Model數(shù)據(jù)對(duì)象時(shí)生成的。
GoJS中的ChangedEvent是狀態(tài)更改的通知,主要是對(duì)象屬性更改。ChangedEvent記錄發(fā)生的更改的種類(lèi)以及足以撤消和重做的足夠信息。
更改的事件由Model和Diagram產(chǎn)生。他們是多播事件,所以你可以調(diào)用Model.addChangedListener和Diagram.addChangedListener,以及相應(yīng)的removeChangedListener方法。為了方便起見(jiàn),您還可以在圖上指定模型更改偵聽(tīng)器:Diagram.addModelChangedListener。 ChangedEvent通過(guò)模型更改偵聽(tīng)收到旨意有一個(gè)非空值ChangedEvent.model。同樣,圖更改偵聽(tīng)器收到的ChangedEvents的ChangedEvent.diagram值將為非null 。
一圖總是將自身注冊(cè)為它的一個(gè)偵聽(tīng)模式,以便它可以自動(dòng)的通知更改模型并相應(yīng)地更新它的零件。此外,UndoManager(如果啟用)會(huì)自動(dòng)偵聽(tīng)對(duì)模型和圖的更改,以便它可以記錄更改歷史記錄并執(zhí)行撤消和重做。
型號(hào)和數(shù)據(jù)變更
模型屬性更改
Model ChangedEvents記錄狀態(tài)更改到模型中的數(shù)據(jù)或模型本身。通過(guò)調(diào)用Model.setDataProperty和Model屬性設(shè)置器來(lái)生成模型的ChangedEvents。
對(duì)于特性的變化,該信息包括所述ChangedEvent.object被修改,則ChangedEvent.propertyName和ChangedEvent.oldValue和ChangedEvent.newValue該屬性的值。屬性更改由ChangedEvent.change屬性值為ChangedEvent,Property標(biāo)識(shí)。
一些更改代表模型的結(jié)構(gòu)更改,而不僅僅是簡(jiǎn)單的模型數(shù)據(jù)更改?!敖Y(jié)構(gòu)”更改是模型負(fù)責(zé)維護(hù)的關(guān)系的插入,修改或刪除。在這種情況下,ChangedEvent.modelChange屬性將是一個(gè)非空字符串,用于命名更改的類(lèi)型。Property ChangedEvent的以下名稱(chēng)對(duì)應(yīng)于結(jié)構(gòu)模型數(shù)據(jù)的更改:
替換Model.nodeDataArray數(shù)組后為“ nodeDataArray ”
“ nodeCategory ”改為Model.setCategoryForNodeData
“ nodeGroupKey ”改為GraphLinksModel.setGroupKeyForNodeData
替換了GraphLinksModel.linkDataArray數(shù)組后的“ linkDataArray ”
“ linkFromKey ”改為由于調(diào)用了GraphLinksModel.setFromKeyForLinkData
“ linkToKey ”改為GraphLinksModel.setToKeyForLinkData
“ linkFromPortId ”改為GraphLinksModel.setFromPortIdForLinkData
“ linkToPortId ”改為GraphLinksModel.setToPortIdForLinkData
“ linkLabelKeys ”改為GraphLinksModel.setLabelKeysForLinkData
“ linkCategory ”改為GraphLinksModel.setCategoryForLinkData
“ nodeParentKey ”改為T(mén)reeModel.setParentKeyForNodeData
“ parentLinkCategory ”改為T(mén)reeModel.setParentLinkCategoryForNodeData
ChangedEvent.modelChange的值將是以下字符串之一。ChangedEvent.propertyName的值取決于已修改的實(shí)際數(shù)據(jù)屬性的名稱(chēng)。例如,對(duì)于模型屬性更改“ linkFromKey”,實(shí)際屬性名稱(chēng)默認(rèn)為“ from”。但是您可能通過(guò)將GraphLinksModel.linkFromKeyProperty設(shè)置為其他一些數(shù)據(jù)屬性名稱(chēng)來(lái)使用其他屬性名稱(chēng)。
通過(guò)調(diào)用Model.setDataProperty,可以在節(jié)點(diǎn)數(shù)據(jù)或鏈接數(shù)據(jù)對(duì)象上更改任何屬性。這樣的調(diào)用將導(dǎo)致屬性名稱(chēng)記錄為ChangedEvent.propertyName。這些情況被視為常規(guī)屬性更改,而不是結(jié)構(gòu)模型更改,因此ChangedEvent.modelChange將為空字符串。當(dāng)然,ChangedEvent.object的值將是已修改的JavaScript對(duì)象。
某些更改可能是暫時(shí)發(fā)生的,因?yàn)槟承┐a(例如在Tool中)可能希望出于其自身目的使用臨時(shí)對(duì)象。但是,您的更改偵聽(tīng)器可能對(duì)此類(lèi)ChangedEvent不感興趣。如果是這樣的話(huà),你可能要忽略ChangedEvent如果Model.skipsUndoManager(或Diagram.skipsUndoManager)為真。
最后,模型本身也會(huì)發(fā)生屬性更改。有關(guān)此類(lèi)屬性的列表,請(qǐng)參見(jiàn)Model,GraphLinksModel和TreeModel的文檔。這些情況也被視為常規(guī)屬性更改,因此ChangedEvent.modelChange將為空字符串。無(wú)論ChangedEvent.model和ChangedEvent.object將是模型本身。
模型集合變更
其他類(lèi)型的更改事件包括ChangedEvent,Insert和ChangedEvent,Remove。除了用于記錄屬性更改的所有前面提到的ChangedEvent屬性之外,ChangedEvent.oldParam和ChangedEvent.newParam還提供了能夠正確撤消和重做更改所需的“索引”信息。
Insert和Remove ChangedEvent的以下名稱(chēng)對(duì)應(yīng)于對(duì)集合的模型更改:
“ nodeDataArray ”改為Model.addNodeData或Model.removeNodeData
“ linkDataArray ”改為GraphLinksModel.addLinkData或GraphLinksModel.removeLinkData
“ linkLabelKeys ”改為GraphLinksModel.addLabelKeyForLinkData 或GraphLinksModel.removeLabelKeyForLinkData
交易次數(shù)
模型更改事件的最后一種類(lèi)型是ChangedEvent,Transaction。這些并不是嚴(yán)格意義上的對(duì)象更改,但它們確實(shí)會(huì)通知事務(wù)何時(shí)開(kāi)始或完成,或者撤消或重做何時(shí)開(kāi)始或完成。
ChangedEvent.propertyName 的以下值描述了剛剛發(fā)生的與事務(wù)相關(guān)的事件的類(lèi)型:
“ StartingFirstTransaction ”
“ StartedTransaction ”
“ CommittingTransaction ”
“ CommittedTransaction ”
“ RolledBackTransaction ”
“ 開(kāi)始撤消 ”
“ 完成撤消 ”
“ 起始重做 ”
“ 完成重做 ”
在每種情況下,ChangedEvent.object是持有一系列ChangedEvent的Transaction。該ChangedEvent.oldValue是事務(wù)的名字-傳遞給串UndoManager.startTransaction或UndoManager.commitTransaction。執(zhí)行交易的各種標(biāo)準(zhǔn)命令和工具記錄了他們采用的交易名稱(chēng)。但是您的代碼可以使用任意數(shù)量的事務(wù)名稱(chēng)。
通常,不應(yīng)在任何事務(wù)ChangedEvent的偵聽(tīng)器中對(duì)模型或其任何數(shù)據(jù)進(jìn)行任何更改。
交易完成后保存模型
事務(wù)完成后,通常想更新服務(wù)器數(shù)據(jù)庫(kù)。使用ChangedEvent.isTransactionFinished只讀屬性可檢測(cè)到這種情況。您將需要實(shí)現(xiàn)一個(gè)Changed偵聽(tīng)器,如下所示:
// notice whenever a transaction or undo/redo has occurred
diagram.addModelChangedListener(function(evt) { if (evt.isTransactionFinished) saveModel(evt.model);
});
Transaction.changes的值將是ChangedEvent的List,按記錄順序。這些ChangedEvents表示對(duì)Model以及對(duì)Diagram或其GraphObject的更改。型號(hào)會(huì)有變化e.model !== null; 圖表會(huì)有變化e.diagram !== null。
逐步保存對(duì)模型的更改
如果您不想在每個(gè)事務(wù)結(jié)束時(shí)保存整個(gè)模型,而只希望對(duì)模型進(jìn)行某些更改,則可以遍歷更改列表以選擇您要關(guān)注的更改。例如,這是一個(gè)偵聽(tīng)器,僅當(dāng)將節(jié)點(diǎn)數(shù)據(jù)添加到Model.nodeDataArray或從Model.nodeDataArray刪除時(shí),才記錄消息。
diagram.addModelChangedListener(function(evt) { // ignore unimportant Transaction events
if (!evt.isTransactionFinished) return; var txn = evt.object; // a Transaction
if (txn === null) return; // iterate over all of the actual ChangedEvents of the Transaction
txn.changes.each(function(e) { // ignore any kind of change other than adding/removing a node
if (e.modelChange !== "nodeDataArray") return; // record node insertions and removals
if (e.change === go.ChangedEvent.Insert) { console.log(evt.propertyName + " added node with key: " + e.newValue.key);
} else if (e.change === go.ChangedEvent.Remove) { console.log(evt.propertyName + " removed node with key: " + e.oldValue.key);
}
});
});
當(dāng)用戶(hù)添加節(jié)點(diǎn)(包括通過(guò)復(fù)制)并刪除節(jié)點(diǎn)時(shí),上述偵聽(tīng)器將發(fā)出消息。事務(wù)事件的ChangedEvent.propertyName(即上面的代碼中的evt)將為“ CommittedTransaction”,“ FinishedUndo”或“ FinishedRedo”。請(qǐng)注意,刪除節(jié)點(diǎn)的“ FinishedUndo”實(shí)際上是在添加該節(jié)點(diǎn),就像撤消插入節(jié)點(diǎn)的操作實(shí)際上是將其刪除一樣。
類(lèi)似地,以下是一個(gè)示例,當(dāng)連接,重新連接或斷開(kāi)鏈接時(shí)發(fā)出通知。這不僅檢查GraphLinksModel.linkDataArray的插入和刪除,還更改鏈接數(shù)據(jù)的“ from”和“ to”屬性。
diagram.addModelChangedListener(function(evt) { // ignore unimportant Transaction events
if (!evt.isTransactionFinished) return; var txn = evt.object; // a Transaction
if (txn === null) return; // iterate over all of the actual ChangedEvents of the Transaction
txn.changes.each(function(e) { // record node insertions and removals
if (e.change === go.ChangedEvent.Property) { if (e.modelChange === "linkFromKey") { console.log(evt.propertyName + " changed From key of link: " +
e.object + " from: " + e.oldValue + " to: " + e.newValue);
} else if (e.modelChange === "linkToKey") { console.log(evt.propertyName + " changed To key of link: " +
e.object + " from: " + e.oldValue + " to: " + e.newValue);
}
} else if (e.change === go.ChangedEvent.Insert && e.modelChange === "linkDataArray") { console.log(evt.propertyName + " added link: " + e.newValue);
} else if (e.change === go.ChangedEvent.Remove && e.modelChange === "linkDataArray") { console.log(evt.propertyName + " removed link: " + e.oldValue);
}
});
});
注意:上面的代碼僅適用于GraphLinksModel,其中鏈接數(shù)據(jù)是單獨(dú)的JavaScript對(duì)象。
查看更新演示,以演示如何在提交事務(wù)或完成撤消或重做操作時(shí)跟蹤模型的更改。常見(jiàn)的模式是遍歷當(dāng)前事務(wù)的ChangedEvents,以便決定在數(shù)據(jù)庫(kù)中記錄什么。
圖表和GraphObject的更改
Diagram ChangedEvents記錄狀態(tài)更改為圖表中的GraphObject或RowColumnDefinition,或圖表中的圖層,或圖表本身。對(duì)于此類(lèi)事件,ChangedEvent.diagram將為非null。
圖的大多數(shù)ChangedEvents都會(huì)記錄屬性更改,例如某些代碼設(shè)置了TextBlock.text屬性或Part.location屬性時(shí)。在某些地方會(huì)生成ChangedEvents來(lái)記錄對(duì)集合的插入或刪除,例如Panel.insertAt。對(duì)于ChangedEvent.Transaction的圖,永遠(yuǎn)不會(huì)有任何ChangedEvents。
盡管圖表的ChangedEvents對(duì)于撤消/重做對(duì)于保持視覺(jué)逼真度很重要,但是在保存模型時(shí)通常會(huì)忽略它們。僅模型的ChangedEvents會(huì)將狀態(tài)更改記錄到模型數(shù)據(jù)。因此,要保存到數(shù)據(jù)庫(kù),您將只考慮那些ChangedEvent.model 不為null的ChangedEvent。
=====================================================
想要購(gòu)買(mǎi)GoJS正版授權(quán)的朋友可以咨詢(xún)慧都官方客服。
更多精彩內(nèi)容,歡迎關(guān)注下方的微信公眾號(hào),及時(shí)獲取產(chǎn)品最新資訊▼▼▼