Skip to Content
示例Nodes

删除中间节点

此示例向你展示了在从链中间移除节点时如何恢复已删除的边。换句话说,如果我们有三个按顺序连接的节点 - a->b->c - 并且我们删除了中间节点 b,此示例向你展示了如何最终得到图 a->c

🌐 This example shows you how to recover deleted edges when you remove a node from the middle of a chain. In other words, if we have three nodes connected in sequence - a->b->c - and we deleted the middle node b, this example shows you how to end up with the graph a->c.

为了实现这一点,我们需要利用一些位:

🌐 To achieve this, we need to make use of a few bits:

  • onNodesDelete 回调让我们知道何时节点被删除。
  • getConnectedEdges 给我们提供与一个节点连接的所有边,无论是作为源节点还是目标节点。
  • getIncomersgetOutgoers 给我们提供了作为源或目标与某个节点相连的节点。

总的来说,这使我们能够将与被删除节点连接的所有节点,重新连接到被删除节点所连接的任何节点上。

🌐 All together, this allows us to take all the nodes connected to the deleted node, and reconnect them to any nodes the deleted node was connected to.

import React, { useCallback } from 'react'; import { ReactFlow, Background, useNodesState, useEdgesState, addEdge, getIncomers, getOutgoers, getConnectedEdges, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; const initialNodes = [ { id: '1', type: 'input', data: { label: 'Start here...' }, position: { x: -150, y: 0 }, }, { id: '2', type: 'input', data: { label: '...or here!' }, position: { x: 150, y: 0 }, }, { id: '3', data: { label: 'Delete me.' }, position: { x: 0, y: 100 } }, { id: '4', data: { label: 'Then me!' }, position: { x: 0, y: 200 } }, { id: '5', type: 'output', data: { label: 'End here!' }, position: { x: 0, y: 300 }, }, ]; const initialEdges = [ { id: '1->3', source: '1', target: '3' }, { id: '2->3', source: '2', target: '3' }, { id: '3->4', source: '3', target: '4' }, { id: '4->5', source: '4', target: '5' }, ]; export default function Flow() { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const onConnect = useCallback((params) => setEdges(addEdge(params, edges)), [edges]); const onNodesDelete = useCallback( (deleted) => { let remainingNodes = [...nodes]; setEdges( deleted.reduce((acc, node) => { const incomers = getIncomers(node, remainingNodes, acc); const outgoers = getOutgoers(node, remainingNodes, acc); const connectedEdges = getConnectedEdges([node], acc); const remainingEdges = acc.filter((edge) => !connectedEdges.includes(edge)); const createdEdges = incomers.flatMap(({ id: source }) => outgoers.map(({ id: target }) => ({ id: `${source}->${target}`, source, target, })), ); remainingNodes = remainingNodes.filter((rn) => rn.id !== node.id); return [...remainingEdges, ...createdEdges]; }, edges), ); }, [nodes, edges], ); return ( <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} onNodesDelete={onNodesDelete} onEdgesChange={onEdgesChange} onConnect={onConnect} fitView attributionPosition="top-right" > <Background /> </ReactFlow> ); }

虽然这个例子不到20行代码,但内容相当丰富。让我们来分解其中的一些部分:

🌐 Although this example is less than 20 lines of code there’s quite a lot to digest. Let’s break some of it down:

  • 我们的 onNodesDelete 回调会被调用,并传入一个参数 - deleted - 它是一个包含所有刚被删除节点的数组。如果你选择一个单独的节点并按下删除键,deleted 将只包含该节点,但如果你进行选择,选择中的所有节点 都会在 deleted 中。
  • 我们创建一个新的边数组 - remainingEdges -,其中包含流中与我们刚刚删除的节点无关的所有边。
  • 我们通过对 incomers 数组进行 flatMapping 来创建另一个边数组。这些是作为源节点与被删除节点连接的节点。对于这些节点中的每一个,我们创建一条新边,连接到 outgoers 数组中的每个节点。这些是作为目标节点与被删除节点连接的节点。

为了简洁,我们使用了对象解构,同时重命名绑定的变量(例如,({ id: source }) => ...) 解构对象的 id 属性并将其绑定到一个名为 source 的新变量),但你不需要这样做

快速参考

🌐 Quick Reference

Last updated on