效果圖如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLjlDZhJmNjRWO5kjMlVWZ4ImNhRzNjZGZmNjYkhjM3E2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
流程節點類型:
1.普通節點
2.分支節點
難點:
1.資料結構定義
2.節點有序渲染
3.分支節點渲染
資料結構:
flowNodesMap:節點映射對象;(以節點id為關鍵字存儲節點資料)
startNodeId :起始節點Id ;(友善從映射對象中找出起始節點資料)
節點資料中關鍵 :
- nextId:下一節點id(若後面無節點預設值為-1)
- preId :前一節點id(起始節點預設值為1)
節點序列化渲染:
getSameLevelIds (flowNodesMap, startNodeId) {
let ret = [startNodeId]
let nextId = flowNodesMap[startNodeId].nextId
while (nextId && nextId !== '-1') {
ret.push(nextId)
nextId = flowNodesMap[nextId].nextId
}
return ret
},
renderNodes (flowNodesMap, startNodeId) {
const nodes = getSameLevelIds(flowNodesMap, startNodeId)
.map((id) => {
let data = {
key: id,
props: {
node: flowNodesMap[id],
},
on: {
delete: this.handleNodeDelete,
},
}
return flowNodesMap[id].type === Enums.NODE_TYPE.BRANCH ? (
<Branch
{...data}
flowNodesMap={flowNodesMap}
renderNodes={this.renderNodes}
></Branch>
) : (
<DealNode {...data} ></DealNode>
)
})
return nodes
},
getSameLevelIds:根據節點映射生成有序數組,
renderNodes:周遊渲染節點 (根據節點類型渲染不同節點)
分支節點渲染:
關鍵點:flowIds資料儲存該分支節點的所有一級條件節點id
const nodes = this.node.flowIds.map((id, index) => {
let conditionNode = this.renderConditionNode(id)
if (index === 0) {
return (
<div class="col-box">
<div class="top-left-cover-line" />
{conditionNode}
<div class="bottom-left-cover-line" />
</div>
)
} else if (index === this.node.flowIds.length - 1) {
return (
<div class="col-box">
<div class="top-right-cover-line" />
{conditionNode}
<div class="bottom-right-cover-line" />
</div>
)
}
return (
<div class="col-box">
{conditionNode}
</div>
)
})
renderConditionNode (id) {
let ret = []
ret.push(<ConditionNode node={this.flowNodesMap[id]} on-delete={this.handleConditionNodeDelete}></ConditionNode>)
//如果該條件節點存在下一節點,則重新判斷節點類型渲染節點 是普通節點還是分支節點
if (this.flowNodesMap[id].nextId) {
ret.push(...this.renderNodes(this.flowNodesMap,this.flowNodesMap[id].nextId))
}
if (ret.length === 1) {
if (!ret[0].data.style) {
ret[0].data.style = {}
}
ret[0].data.style['flex-grow'] = 1
} else {
if (!ret[ret.length - 1].data.style) {
ret[ret.length - 1].data.style = {}
}
ret[ret.length - 1].data.style['flex-grow'] = 1
}
return ret
},
元件樣式自定義
整體結構:節點塊 + 連結線
渲染思路總結:
根據節點映射排列縱向節點,渲染類型為分支節點時,根據flowIds渲染分支的同級條件節點。一條分支以條件節點開頭,渲染分支就以該頭部條件節點為起始節點循環調用renderNode,實作各分支渲染。