@logicflow/core 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/api/logicflow-constructor/index.en.md +106 -0
- package/dist/docs/api/logicflow-constructor/index.zh.md +106 -0
- package/dist/docs/api/logicflow-constructor/use.en.md +61 -0
- package/dist/docs/api/logicflow-constructor/use.zh.md +61 -0
- package/dist/docs/api/logicflow-instance/canvas.en.md +197 -0
- package/dist/docs/api/logicflow-instance/canvas.zh.md +199 -0
- package/dist/docs/api/logicflow-instance/edge.en.md +273 -0
- package/dist/docs/api/logicflow-instance/edge.zh.md +273 -0
- package/dist/docs/api/logicflow-instance/edit-config.en.md +59 -0
- package/dist/docs/api/logicflow-instance/edit-config.zh.md +59 -0
- package/dist/docs/api/logicflow-instance/element.en.md +375 -0
- package/dist/docs/api/logicflow-instance/element.zh.md +379 -0
- package/dist/docs/api/logicflow-instance/event.en.md +326 -0
- package/dist/docs/api/logicflow-instance/event.zh.md +406 -0
- package/dist/docs/api/logicflow-instance/history.en.md +38 -0
- package/dist/docs/api/logicflow-instance/history.zh.md +38 -0
- package/dist/docs/api/logicflow-instance/index.en.md +41 -0
- package/dist/docs/api/logicflow-instance/index.zh.md +41 -0
- package/dist/docs/api/logicflow-instance/node.en.md +308 -0
- package/dist/docs/api/logicflow-instance/node.zh.md +308 -0
- package/dist/docs/api/logicflow-instance/register.en.md +76 -0
- package/dist/docs/api/logicflow-instance/register.zh.md +76 -0
- package/dist/docs/api/logicflow-instance/render-and-data.en.md +179 -0
- package/dist/docs/api/logicflow-instance/render-and-data.zh.md +181 -0
- package/dist/docs/api/logicflow-instance/text.en.md +60 -0
- package/dist/docs/api/logicflow-instance/text.zh.md +60 -0
- package/dist/docs/api/logicflow-instance/theme.en.md +179 -0
- package/dist/docs/api/logicflow-instance/theme.zh.md +179 -0
- package/dist/docs/api/runtime-model/edgeModel.en.md +29 -0
- package/dist/docs/api/runtime-model/edgeModel.zh.md +325 -0
- package/dist/docs/api/runtime-model/graphModel.en.md +275 -0
- package/dist/docs/api/runtime-model/graphModel.zh.md +1153 -0
- package/dist/docs/api/runtime-model/nodeModel.en.md +37 -0
- package/dist/docs/api/runtime-model/nodeModel.zh.md +644 -0
- package/dist/docs/api/type/MainTypes.en.md +598 -0
- package/dist/docs/api/type/MainTypes.zh.md +867 -0
- package/dist/docs/api/type/Theme.en.md +187 -0
- package/dist/docs/api/type/Theme.zh.md +187 -0
- package/dist/docs/api/type/canvas-types.en.md +25 -0
- package/dist/docs/api/type/canvas-types.zh.md +25 -0
- package/dist/docs/api/type/index.en.md +96 -0
- package/dist/docs/api/type/index.zh.md +99 -0
- package/dist/docs/api/type/node-types.en.md +21 -0
- package/dist/docs/api/type/node-types.zh.md +21 -0
- package/dist/docs/api/type/plugin-types.en.md +24 -0
- package/dist/docs/api/type/plugin-types.zh.md +24 -0
- package/dist/docs/index.md +11 -0
- package/dist/docs/tutorial/about.en.md +38 -0
- package/dist/docs/tutorial/about.zh.md +65 -0
- package/dist/docs/tutorial/advanced/dnd.en.md +62 -0
- package/dist/docs/tutorial/advanced/dnd.zh.md +52 -0
- package/dist/docs/tutorial/advanced/edge.en.md +64 -0
- package/dist/docs/tutorial/advanced/edge.zh.md +66 -0
- package/dist/docs/tutorial/advanced/keyboard.en.md +70 -0
- package/dist/docs/tutorial/advanced/keyboard.zh.md +67 -0
- package/dist/docs/tutorial/advanced/node.en.md +338 -0
- package/dist/docs/tutorial/advanced/node.zh.md +338 -0
- package/dist/docs/tutorial/advanced/react.en.md +106 -0
- package/dist/docs/tutorial/advanced/react.zh.md +114 -0
- package/dist/docs/tutorial/advanced/silent-mode.en.md +75 -0
- package/dist/docs/tutorial/advanced/silent-mode.zh.md +71 -0
- package/dist/docs/tutorial/advanced/snapline.en.md +54 -0
- package/dist/docs/tutorial/advanced/vue.en.md +249 -0
- package/dist/docs/tutorial/advanced/vue.zh.md +248 -0
- package/dist/docs/tutorial/ai.en.md +64 -0
- package/dist/docs/tutorial/ai.zh.md +64 -0
- package/dist/docs/tutorial/basic/background.en.md +50 -0
- package/dist/docs/tutorial/basic/canvas.en.md +164 -0
- package/dist/docs/tutorial/basic/canvas.zh.md +183 -0
- package/dist/docs/tutorial/basic/class.en.md +106 -0
- package/dist/docs/tutorial/basic/class.zh.md +103 -0
- package/dist/docs/tutorial/basic/edge.en.md +151 -0
- package/dist/docs/tutorial/basic/edge.zh.md +152 -0
- package/dist/docs/tutorial/basic/event.en.md +70 -0
- package/dist/docs/tutorial/basic/event.zh.md +66 -0
- package/dist/docs/tutorial/basic/grid.en.md +77 -0
- package/dist/docs/tutorial/basic/node.en.md +358 -0
- package/dist/docs/tutorial/basic/node.zh.md +318 -0
- package/dist/docs/tutorial/basic/theme.en.md +154 -0
- package/dist/docs/tutorial/basic/theme.zh.md +157 -0
- package/dist/docs/tutorial/extension/adapter.en.md +446 -0
- package/dist/docs/tutorial/extension/adapter.zh.md +429 -0
- package/dist/docs/tutorial/extension/bpmn-element.en.md +1427 -0
- package/dist/docs/tutorial/extension/bpmn-element.zh.md +1472 -0
- package/dist/docs/tutorial/extension/control.en.md +117 -0
- package/dist/docs/tutorial/extension/control.zh.md +118 -0
- package/dist/docs/tutorial/extension/curved-edge.en.md +46 -0
- package/dist/docs/tutorial/extension/curved-edge.zh.md +46 -0
- package/dist/docs/tutorial/extension/custom.en.md +142 -0
- package/dist/docs/tutorial/extension/custom.zh.md +138 -0
- package/dist/docs/tutorial/extension/dnd-panel.en.md +109 -0
- package/dist/docs/tutorial/extension/dnd-panel.zh.md +109 -0
- package/dist/docs/tutorial/extension/dynamic-group.en.md +606 -0
- package/dist/docs/tutorial/extension/dynamic-group.zh.md +606 -0
- package/dist/docs/tutorial/extension/group.en.md +217 -0
- package/dist/docs/tutorial/extension/group.zh.md +209 -0
- package/dist/docs/tutorial/extension/highlight.en.md +50 -0
- package/dist/docs/tutorial/extension/highlight.zh.md +50 -0
- package/dist/docs/tutorial/extension/insert-node-in-polyline.en.md +52 -0
- package/dist/docs/tutorial/extension/insert-node-in-polyline.zh.md +47 -0
- package/dist/docs/tutorial/extension/intro.en.md +72 -0
- package/dist/docs/tutorial/extension/intro.zh.md +95 -0
- package/dist/docs/tutorial/extension/label.en.md +136 -0
- package/dist/docs/tutorial/extension/label.zh.md +135 -0
- package/dist/docs/tutorial/extension/layout.en.md +156 -0
- package/dist/docs/tutorial/extension/layout.zh.md +156 -0
- package/dist/docs/tutorial/extension/menu.en.md +319 -0
- package/dist/docs/tutorial/extension/menu.zh.md +377 -0
- package/dist/docs/tutorial/extension/minimap.en.md +164 -0
- package/dist/docs/tutorial/extension/minimap.zh.md +180 -0
- package/dist/docs/tutorial/extension/node-resize.en.md +199 -0
- package/dist/docs/tutorial/extension/node-resize.zh.md +221 -0
- package/dist/docs/tutorial/extension/pool.en.md +227 -0
- package/dist/docs/tutorial/extension/pool.zh.md +227 -0
- package/dist/docs/tutorial/extension/proximity-connect.en.md +104 -0
- package/dist/docs/tutorial/extension/proximity-connect.zh.md +107 -0
- package/dist/docs/tutorial/extension/selection.en.md +166 -0
- package/dist/docs/tutorial/extension/selection.zh.md +150 -0
- package/dist/docs/tutorial/extension/snapshot.en.md +276 -0
- package/dist/docs/tutorial/extension/snapshot.zh.md +276 -0
- package/dist/docs/tutorial/get-started.en.md +501 -0
- package/dist/docs/tutorial/get-started.zh.md +139 -0
- package/dist/docs/tutorial/update.en.md +213 -0
- package/dist/docs/tutorial/update.zh.md +212 -0
- package/package.json +5 -3
- package/scripts/postinstall-ai-prompt.js +67 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
nav: 指南
|
|
3
|
+
group:
|
|
4
|
+
title: 进阶
|
|
5
|
+
order: 2
|
|
6
|
+
title: 键盘快捷键
|
|
7
|
+
order: 3
|
|
8
|
+
toc: content
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 快捷键配置
|
|
12
|
+
|
|
13
|
+
通过创建 `LogicFlow` 实例时传入 options 的 keyboard 属性可以开启快捷键,
|
|
14
|
+
可以只配置 enabled 属性,为 true 时,代表开启默认的快捷键。
|
|
15
|
+
|
|
16
|
+
```tsx | pure
|
|
17
|
+
const lf = new LogicFlow({
|
|
18
|
+
container: document.querySelector('#app'),
|
|
19
|
+
keyboard: {
|
|
20
|
+
enabled: true,
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 内置快捷键功能
|
|
26
|
+
|
|
27
|
+
参考不同的产品,内置了复制,粘贴,redo/undo,删除 的快捷键。
|
|
28
|
+
|
|
29
|
+
| 快捷键 | 功能 |
|
|
30
|
+
|:-------------------|:-----|
|
|
31
|
+
| cmd + c 或 ctrl + c | 复制节点 |
|
|
32
|
+
| cmd + v 或 ctrl + v | 粘贴节点 |
|
|
33
|
+
| cmd + z 或 ctrl + z | 撤销操作 |
|
|
34
|
+
| cmd + y 或 ctrl + y | 重做操作 |
|
|
35
|
+
| backspace | 删除操作 |
|
|
36
|
+
|
|
37
|
+
## 自定义快捷键
|
|
38
|
+
|
|
39
|
+
shortcuts 则可以定义用户自定义的一组快捷键
|
|
40
|
+
值得一提的是 keys 的规则,与[mousetrap](https://www.npmjs.com/package/mousetrap)一致。
|
|
41
|
+
|
|
42
|
+
我们以自定义删除功能为例,在删除之前添加一个确认操作。
|
|
43
|
+
|
|
44
|
+
```tsx | pure
|
|
45
|
+
const lf = new LogicFlow({
|
|
46
|
+
// ...
|
|
47
|
+
keyboard: {
|
|
48
|
+
enabled: true,
|
|
49
|
+
shortcuts: [
|
|
50
|
+
{
|
|
51
|
+
keys: ["backspace"],
|
|
52
|
+
callback: () => {
|
|
53
|
+
const r = window.confirm("确定要删除吗?");
|
|
54
|
+
if (r) {
|
|
55
|
+
const elements = lf.getSelectElements(true);
|
|
56
|
+
lf.clearSelectElements();
|
|
57
|
+
elements.edges.forEach((edge) => lf.deleteEdge(edge.id));
|
|
58
|
+
elements.nodes.forEach((node) => lf.deleteNode(node.id));
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
<a href="https://codesandbox.io/embed/logicflow-base10-eerft?fontsize=14&hidenavigation=1&theme=dark&view=preview" target="_blank"> 去 CodeSandbox 查看示例</a>
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
---
|
|
2
|
+
nav: Guide
|
|
3
|
+
group:
|
|
4
|
+
title: Intermediate
|
|
5
|
+
order: 2
|
|
6
|
+
title: Node
|
|
7
|
+
order: 0
|
|
8
|
+
toc: content
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Connection rules
|
|
12
|
+
|
|
13
|
+
At some point, we may need to control how edges are connected, for example, the start node can't be
|
|
14
|
+
connected by other nodes, the end node can't be connected to other nodes, the user node must be
|
|
15
|
+
followed by a judgement node, etc. To achieve this effect, we need to set the following two
|
|
16
|
+
attributes for the node.
|
|
17
|
+
|
|
18
|
+
- `sourceRules` - check rules when the node is used as the start node (source) of an edge
|
|
19
|
+
- `targetRules` - check rules for when the node is the target of an edge.
|
|
20
|
+
|
|
21
|
+
Take a square for example, at the edge we want its next node to be only a circle node, then we
|
|
22
|
+
should add a check rule for `square` as a `source` node.
|
|
23
|
+
|
|
24
|
+
```tsx | pure
|
|
25
|
+
import { RectNode, RectNodeModel } from '@logicflow/core'
|
|
26
|
+
|
|
27
|
+
class SquareModel extends RectNodeModel {
|
|
28
|
+
initNodeData(data) {
|
|
29
|
+
super.initNodeData(data)
|
|
30
|
+
|
|
31
|
+
const circleOnlyAsTarget = {
|
|
32
|
+
message: 'The next node of a square node can only be a round node',
|
|
33
|
+
validate: (sourceNode, targetNode, sourceAnchor, targetAnchor) => {
|
|
34
|
+
return targetNode.type === 'circle'
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
this.sourceRules.push(circleOnlyAsTarget)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
In the above example, we added a checking rule to the `sourceRules` property of `model`, which is an
|
|
43
|
+
object for which we need to provide the `message` and `validate` properties.
|
|
44
|
+
|
|
45
|
+
The `message` attribute is the error message that is thrown when the check rule is not satisfied,
|
|
46
|
+
and `validate` is the callback function that is passed in to check the rule. The `validate` method
|
|
47
|
+
takes two arguments, the source and the target of the edge, and we can decide whether to pass
|
|
48
|
+
the check based on the information in the arguments, and its return value is a boolean.
|
|
49
|
+
|
|
50
|
+
:::warning
|
|
51
|
+
When we do an edge operation on the panel, LogicFlow checks each rule and will only connect if **all
|
|
52
|
+
** of them pass.
|
|
53
|
+
:::
|
|
54
|
+
|
|
55
|
+
When edging, LogicFlow throws the event `connection:not-allowed` externally if a custom rule is not
|
|
56
|
+
passed after the mouse is released (the `validate` method returns `false`).
|
|
57
|
+
|
|
58
|
+
```tsx | pure
|
|
59
|
+
lf.on('connection:not-allowed', (msg) => {
|
|
60
|
+
console.log(msg)
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Here is an example to show the connection state by **setting the style of the node in different
|
|
65
|
+
states** 👇.
|
|
66
|
+
|
|
67
|
+
In the node model, there is a state attribute, when the node connection rule check does not pass,
|
|
68
|
+
the value of the state attribute is 5. We can use this attribute to realize the effect of the hint
|
|
69
|
+
that the connection is a node.
|
|
70
|
+
|
|
71
|
+
<code id="node-connect" src="../../../src/tutorial/advanced/node/connect"></code>
|
|
72
|
+
|
|
73
|
+
## Move
|
|
74
|
+
|
|
75
|
+
There are times when we need more granular control over when a node can and cannot move, such as
|
|
76
|
+
when implementing a grouping plugin, where we need to control that grouped node children are not
|
|
77
|
+
allowed to move out of the group. Similar to the connectivity rules, we can add a rule function to
|
|
78
|
+
the node's `moveRules`.
|
|
79
|
+
|
|
80
|
+
```tsx | pure
|
|
81
|
+
class MovableNodeModel extends RectNodeModel {
|
|
82
|
+
initNodeData(data) {
|
|
83
|
+
super.initNodeData(data);
|
|
84
|
+
this.moveRules.push((model, deltaX, deltaY) => {
|
|
85
|
+
// ...
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
There is support in `graphModel` for adding global move rules, e.g. when moving node A, expect to
|
|
92
|
+
move node B along with it.
|
|
93
|
+
|
|
94
|
+
```tsx | pure
|
|
95
|
+
lf.graphModel.addNodeMoveRules((model, deltaX, deltaY) => {
|
|
96
|
+
// If the move is a grouping, then the child nodes of the grouping move with it.
|
|
97
|
+
if (model.isGroup && model.children) {
|
|
98
|
+
lf.graphModel.moveNodes(model.children, deltaX, deltaY, true);
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
<code id="node-movable" src="../../../src/tutorial/advanced/node/movable"></code>
|
|
105
|
+
|
|
106
|
+
## Anchor Points
|
|
107
|
+
|
|
108
|
+
For various base type nodes, we have built-in default anchor points.LogicFlow supports customizing
|
|
109
|
+
the anchor point of a node by overriding the method of getting the anchor point.
|
|
110
|
+
|
|
111
|
+
<code id="node-sql" src="../../../src/tutorial/advanced/node/sql"></code>
|
|
112
|
+
|
|
113
|
+
In the above example, when we customize the anchors, we can not only define the number and position
|
|
114
|
+
of the anchors, but we can also add any attributes to the anchors. With these attributes, we can
|
|
115
|
+
then do a lot of additional things. For example, we can add a check rule to allow nodes to be
|
|
116
|
+
connected only from the right and not from the left, or we can add an id to save the current
|
|
117
|
+
connection from that anchor to that anchor when we get the data.
|
|
118
|
+
|
|
119
|
+
:::warning
|
|
120
|
+
Is sure to ensure that the anchor id is unique, otherwise there may be problems with inaccurate
|
|
121
|
+
checksums in the concatenation rules.
|
|
122
|
+
In actual development, there is a need to hide anchors, you can refer to the GitHub
|
|
123
|
+
issue [How to hide anchors?](https://github.com/didi/LogicFlow/issues/454),Go to CodeSandbox
|
|
124
|
+
for [examples](https://codesandbox.io/s/reverent-haslett-dkb9n?file=/step_14_hideAnchor/index.js)
|
|
125
|
+
:::
|
|
126
|
+
|
|
127
|
+
### customTargetAnchor (Custom Anchor Drop Target)
|
|
128
|
+
|
|
129
|
+
When you drag a connection from an anchor and release it on a node, LogicFlow uses the mouse release position (`position`) to decide which anchor on the target node to connect to.
|
|
130
|
+
|
|
131
|
+
- Default behavior: connect to the anchor closest to `position`
|
|
132
|
+
- Custom behavior: pass `customTargetAnchor` during LogicFlow initialization to return the preferred anchor first; if it returns `undefined`, it falls back to the default behavior
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
<code id="node-custom-target-anchor" src="../../../src/tutorial/advanced/node/customTargetAnchor"></code>
|
|
136
|
+
|
|
137
|
+
## Text
|
|
138
|
+
|
|
139
|
+
LogicFlow supports customizing the appearance and editing state of node text.
|
|
140
|
+
References [nodeModel API](../../api/runtime-model/nodeModel.en.md) `textObject`
|
|
141
|
+
|
|
142
|
+
```tsx | pure
|
|
143
|
+
class CustomNodeModel extends RectNodeModel {
|
|
144
|
+
initNodeData(data) {
|
|
145
|
+
super.initNodeData(data)
|
|
146
|
+
this.text.draggable = false;
|
|
147
|
+
this.text.editable = false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
getTextStyle() {
|
|
151
|
+
const style = super.getTextStyle();
|
|
152
|
+
style.fontSize = 16;
|
|
153
|
+
style.color = 'red';
|
|
154
|
+
return style;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## HTML Nodes
|
|
160
|
+
|
|
161
|
+
LogicFlow built-in basic HTML nodes and other basic nodes are not the same, we can use LogicFlow's
|
|
162
|
+
customization mechanism, the implementation of a variety of forms of HTML nodes, and HTML nodes can
|
|
163
|
+
be rendered using any framework for the internal.
|
|
164
|
+
|
|
165
|
+
The following is an example of an HTML node 👇.
|
|
166
|
+
|
|
167
|
+
<code id="node-html-node" src="../../../src/tutorial/advanced/node/htmlNode/index"></code>
|
|
168
|
+
|
|
169
|
+
## React nodes
|
|
170
|
+
|
|
171
|
+
Since a custom html node exposes a DOM node to the outside world, you can use the framework's
|
|
172
|
+
existing capabilities to render the node. In react, we utilize the `render` method of `reactDom` to
|
|
173
|
+
render the React component to the dom node.
|
|
174
|
+
|
|
175
|
+
<code id="node-react-node" src="../../../src/tutorial/advanced/node/reactNode/index"></code>
|
|
176
|
+
|
|
177
|
+
## Vue Nodes
|
|
178
|
+
|
|
179
|
+
<details> <summary>code expansion</summary>
|
|
180
|
+
|
|
181
|
+
```tsx | pure
|
|
182
|
+
import { HtmlNode, HtmlNodeModel } from "@logicflow/core";
|
|
183
|
+
import { createApp, ref, h } from 'vue';
|
|
184
|
+
import VueNode from './VueNode.vue';
|
|
185
|
+
|
|
186
|
+
class VueHtmlNode extends HtmlNode {
|
|
187
|
+
constructor(props) {
|
|
188
|
+
super(props)
|
|
189
|
+
this.isMounted = false
|
|
190
|
+
this.r = h(VueNode, {
|
|
191
|
+
properties: props.model.getProperties(),
|
|
192
|
+
text: props.model.inputData,
|
|
193
|
+
})
|
|
194
|
+
this.app = createApp({
|
|
195
|
+
render: () => this.r
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
setHtml(rootEl) {
|
|
200
|
+
if (!this.isMounted) {
|
|
201
|
+
this.isMounted = true
|
|
202
|
+
const node = document.createElement('div')
|
|
203
|
+
rootEl.appendChild(node)
|
|
204
|
+
this.app.mount(node)
|
|
205
|
+
} else {
|
|
206
|
+
this.r.component.props.properties = this.props.model.getProperties()
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
class VueHtmlNodeModel extends HtmlNodeModel {
|
|
212
|
+
setAttributes() {
|
|
213
|
+
this.width = 300;
|
|
214
|
+
this.height = 100;
|
|
215
|
+
this.text.editable = false;
|
|
216
|
+
this.inputData = this.text.value
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
getOutlineStyle() {
|
|
220
|
+
const style = super.getOutlineStyle();
|
|
221
|
+
style.stroke = 'none';
|
|
222
|
+
style.hover.stroke = 'none';
|
|
223
|
+
return style;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export default {
|
|
228
|
+
type: 'vue-html',
|
|
229
|
+
model: VueHtmlNodeModel,
|
|
230
|
+
view: VueHtmlNode
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
</details>
|
|
235
|
+
|
|
236
|
+
## External Communication
|
|
237
|
+
|
|
238
|
+
When there is a need for a custom node to interact with the outside world, such as clicking a button
|
|
239
|
+
on a custom HTML node that triggers an external method, you can use LogicFlow's custom event
|
|
240
|
+
mechanism to do so.
|
|
241
|
+
|
|
242
|
+
```tsx | pure
|
|
243
|
+
// view.js
|
|
244
|
+
class VueHtmlNode extends HtmlNode {
|
|
245
|
+
constructor(props) {
|
|
246
|
+
super(props);
|
|
247
|
+
this.isMounted = false;
|
|
248
|
+
this.r = h(VueNode, {
|
|
249
|
+
properties: props.model.getProperties(),
|
|
250
|
+
text: props.model.inputData,
|
|
251
|
+
onBtnClick: (i) => {
|
|
252
|
+
props.graphModel.eventCenter.emit("custom:onBtnClick", i);
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
this.app = createApp({
|
|
256
|
+
render: () => this.r,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
setHtml(rootEl) {
|
|
261
|
+
if (!this.isMounted) {
|
|
262
|
+
this.isMounted = true;
|
|
263
|
+
const node = document.createElement("div");
|
|
264
|
+
rootEl.appendChild(node);
|
|
265
|
+
this.app.mount(node);
|
|
266
|
+
} else {
|
|
267
|
+
this.r.component.props.properties = this.props.model.getProperties();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
getText() {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// flow.js
|
|
277
|
+
const lf = new LogicFlow();
|
|
278
|
+
lf.render();
|
|
279
|
+
lf.on("custom:onBtnClick", () => {});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
:::success{title=tip}
|
|
283
|
+
If a scheme is expected to be passed externally for use in a custom node. Since `lf` instances are
|
|
284
|
+
not directly accessible in the custom node, binding a method directly to lf is not supported. But
|
|
285
|
+
the custom node has access to the model object of the entire graph, `graphModel`, so it is possible
|
|
286
|
+
to bind this method to `graphModel`. In addition, `lf` has basically all the built-in methods
|
|
287
|
+
in `graphModel`, so you can just use `graphModel` to get the flowchart related data when developing
|
|
288
|
+
a custom node.
|
|
289
|
+
:::
|
|
290
|
+
|
|
291
|
+
## Updates
|
|
292
|
+
|
|
293
|
+
HTML nodes currently trigger node updates by modifying properties.
|
|
294
|
+
|
|
295
|
+
```tsx | pure
|
|
296
|
+
class CustomComponent extends Component {
|
|
297
|
+
// ...
|
|
298
|
+
shouldUpdate() {
|
|
299
|
+
if (this.preProperties && this.preProperties === this.currentProperties) return
|
|
300
|
+
this.preProperties = this.currentProperties
|
|
301
|
+
return true
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
componentDidMount() {
|
|
305
|
+
if (this.shouldUpdate()) {
|
|
306
|
+
this.setHtml(this.rootEl)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
componentDidUpdate() {
|
|
311
|
+
if (this.shouldUpdate()) {
|
|
312
|
+
this.setHtml(this.rootEl)
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
//..
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
If you expect changes to other content to trigger node updates, you can override shouldUpdate
|
|
321
|
+
(related issue. [#1208](https://github.com/didi/LogicFlow/issues/1208))
|
|
322
|
+
|
|
323
|
+
```tsx | pure
|
|
324
|
+
class CustomComponent extends Component {
|
|
325
|
+
|
|
326
|
+
shouldUpdate() {
|
|
327
|
+
if (this.preProperties &&
|
|
328
|
+
this.preProperties === this.currentProperties &&
|
|
329
|
+
this.preText === this.props.model.text.value
|
|
330
|
+
) {
|
|
331
|
+
return
|
|
332
|
+
}
|
|
333
|
+
this.preProperties = this.currentProperties
|
|
334
|
+
this.preText = this.props.model.text.value
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|