feat: 后端全量更新 - 含所有本次需求
- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
This commit is contained in:
Executable
+280
@@ -0,0 +1,280 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>GoJS Changed Events -- Northwoods Software</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<script src="../release/go.js"></script>
|
||||
<script src="goIntro.js"></script>
|
||||
</head>
|
||||
<body onload="goIntro()">
|
||||
<div id="container" class="container-fluid">
|
||||
<div id="content">
|
||||
|
||||
<h1>Changed Events</h1>
|
||||
<p>
|
||||
There are three basic kinds of events that <b>GoJS</b> generates:
|
||||
<a>DiagramEvent</a>s, <a>InputEvent</a>s, and <a>ChangedEvent</a>s.
|
||||
This page talks about the latter, which are generated as <a>Diagram</a>s, <a>GraphObject</a>s,
|
||||
<a>Model</a>s, or Model data objects are modified.
|
||||
See the page <a href="events.html">Events</a> for the former two kinds of events.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a>ChangedEvent</a>s in <b>GoJS</b> are notifications of state changes, mostly object property changes.
|
||||
The ChangedEvent records the kind of change that occurred and enough information to be able to undo and redo them.
|
||||
</p>
|
||||
<p>
|
||||
Changed events are produced by both <a>Model</a> and <a>Diagram</a>.
|
||||
They are multicast events, so you can call <a>Model.addChangedListener</a> and <a>Diagram.addChangedListener</a>,
|
||||
as well as the corresponding removeChangedListener methods.
|
||||
For convenience you can also specify a Model change listener on a Diagram: <a>Diagram.addModelChangedListener</a>.
|
||||
<a>ChangedEvent</a>s received by a Model change listener will have a non-null value for <a>ChangedEvent.model</a>.
|
||||
Similarly, ChangedEvents received by a Diagram change listener will have non-null value for <a>ChangedEvent.diagram</a>.
|
||||
</p>
|
||||
<p>
|
||||
A <a>Diagram</a> always registers itself as a listener on its <a>Model</a>, so that it can automatically
|
||||
notice changes to the model and update its Parts accordingly.
|
||||
Furthermore the <a>UndoManager</a>, if enabled, automatically listens to changes to both the model and the diagram,
|
||||
so that it can record the change history and perform undo and redo.
|
||||
</p>
|
||||
|
||||
<h2 id="ModelAndDataChanges">Model and Data changes</h2>
|
||||
|
||||
<h3 id="ModelPropertyChanges">Model property changes</h3>
|
||||
<p>
|
||||
Model ChangedEvents record state changes either to data in a model or to the <a>Model</a> itself.
|
||||
ChangedEvents for models are generated by calls to <a>Model.setDataProperty</a> and by <a>Model</a> property setters.
|
||||
</p>
|
||||
<p>
|
||||
For property changes, that information includes the <a>ChangedEvent.object</a> that was modified,
|
||||
the <a>ChangedEvent.propertyName</a>, and the <a>ChangedEvent.oldValue</a> and <a>ChangedEvent.newValue</a> values
|
||||
for that property.
|
||||
Property changes are identified by the <a>ChangedEvent.change</a> property value being <a>ChangedEvent,Property</a>.
|
||||
</p>
|
||||
<p>
|
||||
Some changes represent structural changes to the model, not just simple model data changes.
|
||||
"Structural" changes are the insertion, modification, or removal of relationships that the model is responsible for maintaining.
|
||||
In such cases the <a>ChangedEvent.modelChange</a> property will be a non-empty string naming the kind of change.
|
||||
The following names for Property <a>ChangedEvent</a>s correspond to structural model data changes:
|
||||
</p>
|
||||
<ul>
|
||||
<li>"<b>nodeDataArray</b>", when the <a>Model.nodeDataArray</a> Array has been replaced</li>
|
||||
<li>"<b>nodeCategory</b>", due to a call to <a>Model.setCategoryForNodeData</a></li>
|
||||
|
||||
<li>"<b>nodeGroupKey</b>", due to a call to <a>GraphLinksModel.setGroupKeyForNodeData</a></li>
|
||||
<li>"<b>linkDataArray</b>", when the <a>GraphLinksModel.linkDataArray</a> Array has been replaced</li>
|
||||
<li>"<b>linkFromKey</b>", due to a call to <a>GraphLinksModel.setFromKeyForLinkData</a></li>
|
||||
<li>"<b>linkToKey</b>", due to a call to <a>GraphLinksModel.setToKeyForLinkData</a></li>
|
||||
<li>"<b>linkFromPortId</b>", due to a call to <a>GraphLinksModel.setFromPortIdForLinkData</a></li>
|
||||
<li>"<b>linkToPortId</b>", due to a call to <a>GraphLinksModel.setToPortIdForLinkData</a></li>
|
||||
<li>"<b>linkLabelKeys</b>", due to a call to <a>GraphLinksModel.setLabelKeysForLinkData</a></li>
|
||||
<li>"<b>linkCategory</b>", due to a call to <a>GraphLinksModel.setCategoryForLinkData</a></li>
|
||||
|
||||
<li>"<b>nodeParentKey</b>", due to a call to <a>TreeModel.setParentKeyForNodeData</a></li>
|
||||
<li>"<b>parentLinkCategory</b>", due to a call to <a>TreeModel.setParentLinkCategoryForNodeData</a></li>
|
||||
</ul>
|
||||
<p>
|
||||
The value of <a>ChangedEvent.modelChange</a> will be one of these strings.
|
||||
The value of <a>ChangedEvent.propertyName</a> depends on the name of the actual data property that was modified.
|
||||
For example, for the model property change "linkFromKey", the actual property name defaults to "from".
|
||||
But you might be using a different property name by having set <a>GraphLinksModel.linkFromKeyProperty</a> to some other data property name.
|
||||
</p>
|
||||
<p>
|
||||
Any property can be changed on a node data or link data object, by calling <a>Model.setDataProperty</a>.
|
||||
Such a call will result in the property name to be recorded as the <a>ChangedEvent.propertyName</a>.
|
||||
These cases are treated as normal property changes, not structural model changes,
|
||||
so <a>ChangedEvent.modelChange</a> will be the empty string.
|
||||
The value of <a>ChangedEvent.object</a> will of course be the JavaScript object that was modified.
|
||||
</p>
|
||||
<p>
|
||||
Some changes may happen temporarily because some code, such as in a Tool, might want to use temporary objects for their own purposes.
|
||||
However your change listener might not be interested in such <a>ChangedEvent</a>s.
|
||||
If that is the case, you may want to ignore the ChangedEvent if <a>Model.skipsUndoManager</a> (or <a>Diagram.skipsUndoManager</a>) is true.
|
||||
</p>
|
||||
<p>
|
||||
Finally, there are property changes on the model itself.
|
||||
For a listing of such properties, see the documentation for <a>Model</a>, <a>GraphLinksModel</a>, and <a>TreeModel</a>.
|
||||
These cases are also treated as normal property changes, so <a>ChangedEvent.modelChange</a> will be the empty string.
|
||||
Both <a>ChangedEvent.model</a> and <a>ChangedEvent.object</a> will be the model itself.
|
||||
</p>
|
||||
|
||||
<h3 id="ModelCollectionChanges">Model collection changes</h3>
|
||||
<p>
|
||||
Other kinds of changed events include <a>ChangedEvent,Insert</a> and <a>ChangedEvent,Remove</a>.
|
||||
In addition to all of the previously mentioned ChangedEvent properties used to record a property change,
|
||||
the <a>ChangedEvent.oldParam</a> and <a>ChangedEvent.newParam</a> provide the "index" information
|
||||
needed to be able to properly undo and redo the change.
|
||||
</p>
|
||||
<p>
|
||||
The following names for Insert and Remove <a>ChangedEvent</a>s correspond to model changes to collections:
|
||||
</p>
|
||||
<ul>
|
||||
<li>"<b>nodeDataArray</b>", due to a call to <a>Model.addNodeData</a> or <a>Model.removeNodeData</a></li>
|
||||
<li>"<b>linkDataArray</b>", due to a call to <a>GraphLinksModel.addLinkData</a> or <a>GraphLinksModel.removeLinkData</a></li>
|
||||
<li>"<b>linkLabelKeys</b>", due to a call to <a>GraphLinksModel.addLabelKeyForLinkData</a>
|
||||
or <a>GraphLinksModel.removeLabelKeyForLinkData</a></li>
|
||||
</ul>
|
||||
|
||||
<h3 id="Transactions">Transactions</h3>
|
||||
<p>
|
||||
The final kind of model changed event is <a>ChangedEvent,Transaction</a>.
|
||||
These are not strictly object changes in the normal sense, but they do notify when a transaction starts or finishes,
|
||||
or when an undo or redo starts or finishes.
|
||||
</p>
|
||||
<p>
|
||||
The following values of <a>ChangedEvent.propertyName</a> describe the kind of transaction-related event that just occurred:
|
||||
</p>
|
||||
<ul>
|
||||
<li>"<b>StartingFirstTransaction</b>"</li>
|
||||
<li>"<b>StartedTransaction</b>"</li>
|
||||
<li>"<b>CommittingTransaction</b>"</li>
|
||||
<li>"<b>CommittedTransaction</b>"</li>
|
||||
<li>"<b>RolledBackTransaction</b>"</li>
|
||||
<li>"<b>StartingUndo</b>"</li>
|
||||
<li>"<b>FinishedUndo</b>"</li>
|
||||
<li>"<b>StartingRedo</b>"</li>
|
||||
<li>"<b>FinishedRedo</b>"</li>
|
||||
</ul>
|
||||
<p>
|
||||
In each case the <a>ChangedEvent.object</a> is the <a>Transaction</a> holding a sequence of <a>ChangedEvent</a>s.
|
||||
The <a>ChangedEvent.oldValue</a> is the name of the transaction --
|
||||
the string passed to <a>UndoManager.startTransaction</a> or <a>UndoManager.commitTransaction</a>.
|
||||
The various standard commands and tools that perform transactions document the transaction name(s) that they employ.
|
||||
But your code can employ as many transaction names as you like.
|
||||
</p>
|
||||
<p class="box bg-danger">
|
||||
As a general rule, you should not make any changes to the model or any of its data in a listener
|
||||
for any Transaction ChangedEvent.
|
||||
</p>
|
||||
|
||||
<h3 id="SavingModelWhenTransactionsComplete">Saving the Model when Transactions Complete</h3>
|
||||
<p>
|
||||
It is commonplace to want to update a server database when a transaction has finished.
|
||||
Use the <a>ChangedEvent.isTransactionFinished</a> read-only property to detect that case.
|
||||
You'll want to implement a Changed listener as follows:
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
// notice whenever a transaction or undo/redo has occurred
|
||||
diagram.addModelChangedListener(function(evt) {
|
||||
if (evt.isTransactionFinished) saveModel(evt.model);
|
||||
});
|
||||
</pre>
|
||||
<p>
|
||||
The value of <a>Transaction.changes</a> will be a List of <a>ChangedEvent</a>s, in the order that they were recorded.
|
||||
Those ChangedEvents represent changes both to the <a>Model</a> and to the <a>Diagram</a> or its <a>GraphObject</a>s.
|
||||
Model changes will have <code>e.model !== null</code>; diagram changes will have <code>e.diagram !== null</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="IncrementallySavingChangesToModel">Incrementally Saving Changes to the Model</h3>
|
||||
<p>
|
||||
If you do not want to save the whole model at the end of each transaction, but only certain changes to the model,
|
||||
you can iterate over the list of changes to pick out the ones that you care about.
|
||||
For example, here is a listener that logs a message only when node data is added to or removed from the <a>Model.nodeDataArray</a>.
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
</pre>
|
||||
<p>
|
||||
The above listener will put out messages as the user adds nodes (including by copying) and deletes nodes.
|
||||
The <a>ChangedEvent.propertyName</a> of the Transaction event (i.e. <i>evt</i> in the code above)
|
||||
will be either "CommittedTransaction", "FinishedUndo", or "FinishedRedo".
|
||||
Note that a "FinishedUndo" of the removal of a node is really adding the node,
|
||||
just as the undo of the insertion of a node actually removes it.
|
||||
</p>
|
||||
<p>
|
||||
Similarly, here is an example of noticing when links are connected, reconnected, or disconnected.
|
||||
This not only checks for insertions to and removals from <a>GraphLinksModel.linkDataArray</a>,
|
||||
but also changes to the "from" and the "to" properties of the link data.
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
</pre>
|
||||
<p>
|
||||
Note: the above code only works for a <a>GraphLinksModel</a>, where the link data are separate JavaScript objects.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Look at the <a href="../samples/UpdateDemo.html">Update Demo</a> for a demonstration of how you can keep
|
||||
track of changes to a model when a transaction is committed or when an undo or redo is finished.
|
||||
The common pattern is to iterate over the ChangedEvents of the current Transaction
|
||||
in order to decide what to record in a database.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It is also possible to send incremental updates to a database using <a>Model.toIncrementalJson</a> or <a>Model.toIncrementalData</a>,
|
||||
which iterate over the changes in a transaction and group them into a JSON-formatted string or an object representing any updates.
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
diagram.addModelChangedListener(function(e) {
|
||||
// ignore unimportant Transaction events
|
||||
if (!evt.isTransactionFinished) return;
|
||||
var json = e.model.toIncrementalJson(e);
|
||||
var data = e.model.toIncrementalData(e);
|
||||
... send to server/database ...
|
||||
});
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="DiagramAndGraphObjectChanges">Diagram and GraphObject changes</h2>
|
||||
<p>
|
||||
Diagram ChangedEvents record state changes to <a>GraphObject</a>s or <a>RowColumnDefinition</a>s in a diagram,
|
||||
or to a <a>Layer</a> in a diagram, or to the <a>Diagram</a> itself.
|
||||
For such events, <a>ChangedEvent.diagram</a> will be non-null.
|
||||
</p>
|
||||
<p>
|
||||
Most ChangedEvents for diagrams record property changes, such as when some code sets the <a>TextBlock.text</a> property
|
||||
or the <a>Part.location</a> property.
|
||||
There are a few places which generate ChangedEvents recording insertions into or removals from collections,
|
||||
such as <a>Panel.insertAt</a>.
|
||||
There are never any ChangedEvents for diagrams that are <a>ChangedEvent,Transaction</a>.
|
||||
</p>
|
||||
<p>
|
||||
Although ChangedEvents for diagrams are important for undo/redo in order to retain visual fidelity,
|
||||
one normally ignores them when saving models. Only ChangedEvents for models record state changes to model data.
|
||||
So for saving to a database, you will want to consider only those ChangedEvents for which <a>ChangedEvent.model</a> is non-null.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user