Skip to content

句柄简介

¥Introduction to Handles

句柄是通常放置在节点边框上的小圆圈。它们用于通过将连接线从一个句柄拖到另一个句柄来连接节点,从而在节点之间建立连接 (边缘)。

¥Handles are the small circles that are usually placed on the borders of a node. They are used to connect nodes together by dragging a connection-line from one handle to another, resulting in a connection (Edge) between the nodes.

句柄是 VueFlow 的重要组成部分,因为它们是用户在节点之间创建边的主要交互点。

¥Handles are a crucial part of VueFlow, as they are the main interaction point for a user to create edges between nodes.

如果没有句柄,节点之间基本上不可能创建边,因为句柄用于计算边的源点和目标点。

¥Without handles, it is basically impossible to create edges between nodes, as the handles are used to calculate the source and target points for edges.

<Handle> 组件

¥<Handle> Component

<Handle> 组件是 @vue-flow/core 导出的组件,可用于为节点创建句柄。它是 <div> 元素的封装器,提供启动连接所需的事件处理程序绑定。

¥The <Handle> component is a component exported by @vue-flow/core that you can use to create a handle for a node. It is a wrapper around a <div> element that provides the necessary event handler bindings to start connections.

<Handle> 组件可用于(自定义)节点组件,为节点创建句柄。在节点组件上下文之外使用 <Handle> 组件将无法正常工作,因此请尽量避免这种情况。

¥The <Handle> component can be used in a (custom) node component to create handles for the node. Using <Handle> components outside a node component context will not work as expected, so try to avoid this.

vue
<script setup>
import { Handle } from '@vue-flow/core'
  
defineProps(['id', 'sourcePosition', 'targetPosition', 'data'])
</script>

<template>
  <Handle type="source" :position="sourcePosition" />
  
  <span>{{ data.label }}</span>
  
  <Handle type="target" :position="targetPosition" />
</template>

句柄位置

¥Handle Positions

句柄可以放置在以下位置:

¥Handles can be placed on the following positions:

  • Top

  • Right

  • Bottom

  • Left

每个位置对应节点的一侧。句柄的位置还决定了从句柄绘制或向句柄绘制时边缘弯曲的方向。

¥Each position corresponds to a side of the node. The position of the handle also determines which direction an edge will bend towards when drawn from and to a handle.

例如,带有 position="Position.Top" 的句柄将导致从该句柄绘制时边向顶部弯曲。带有 position="Position.Right" 的句柄会导致绘制到该句柄的边向左弯曲。

¥For example a handle with position="Position.Top" will result in an edge that bends to the top when drawn from that handle. A handle with position="Position.Right" will result in an edge that bends to the left when drawn to that handle.

调整句柄位置

¥Adjusting Handle Positions

句柄使用 CSS 以 absolute 位置定位在其各自的一侧。这意味着你可以通过将句柄包裹在具有 relative 位置的容器中来调整句柄与哪个元素对齐。

¥Handles are positioned on their respective side using CSS with an absolute position. That means you can adjust what element a handle aligns itself with by wrapping it in a container that has a relative position.

vue
<template>
  <div>
    <span>{{ data.label }}</span>

    <div style="position: relative; padding: 10px">
      <Handle type="source" :position="Position.Right" />


      <Handle type="target" :position="Position.Left" />
    </div>
  </div>
</template>

多个句柄

¥Multiple Handles

一个节点可以有多个句柄,句柄的数量不受限制,你可以根据需要使用任意数量的句柄。使用同一类型的多个句柄(sourcetarget)时,每个句柄都需要具有唯一的 ID。

¥A node can have multiple handles, the number of handles is not limited and you can use as many handles as you need. When using multiple handles of the same type (source or target), each handle needs to have a unique id.

vue
<!-- each of these handles needs a unique id since we're using two `source` type handles -->
<Handle id="source-a" type="source" :position="Position.Right" />
<Handle id="source-b" type="source" :position="Position.Right" />

<!-- each of these handles needs a unique id since we're using two `target` type handles -->
<Handle id="target-a" type="target" :position="Position.Left" />
<Handle id="target-b" type="target" :position="Position.Left" />

id prop 用于在节点之间创建边时标识句柄。如果未提供 id,则将使用所需类型的第一个句柄。

¥The id prop is used to identify the handle when creating edges between nodes. If no id is provided, the first handle of the necessary type will be used.

ts
const { onConnect } = useVueFlow()

onConnect(({ source, target, sourceHandle, targetHandle }) => {
  console.log('source', source)
  console.log('target', target)
  // these are the handle ids of the source and target node
  // if no id is specified these will be `null`, meaning the first handle of the necessary type will be used
  console.log('sourceHandle', sourceHandle)
  console.log('targetHandle', targetHandle)
})

使用多个句柄定位

¥Positioning with Multiple Handles

有时你想在同一侧添加多个句柄。在这种情况下,你通常会看到两个句柄彼此叠放,而不是彼此相邻。句柄不会自动布局,因此你需要手动调整其位置。

¥Sometimes you want to add multiple handles to the same side. In that case you often end up having two handles on top of each other instead of next to each other. Handles will not layout themselves automatically, so you need to manually adjust their position.

你可以使用 CSS 样式来实现。例如,你可以设置 topbottom 属性,以将句柄定位在节点右侧的顶部和底部。

¥You can do so using CSS styles. For example, you can set the top and bottom properties to position the handles on the top and bottom of the right side of the node.

vue
<Handle id="source-a" type="source" :position="Position.Right" style="top: 10px" />
<Handle id="source-b" type="source" :position="Position.Right" style="bottom: 10px; top: auto;" />

隐藏句柄

¥Hidden Handles

在某些情况下,你可能根本不想显示句柄。你可以通过将 opacity: 0 设置为句柄的样式来隐藏该句柄。

¥In some cases you might not want to display a handle at all. You can hide a handle by setting opacity: 0 as the styles for that handle.

你不能通过从 DOM 中移除句柄(例如使用 v-ifv-show)来隐藏它,因为这会破坏边的计算。

¥You cannot hide a handle by removing it from the DOM (for example using v-if or v-show) as that would break the calculations for the edges.

vue
<Handle type="source" :position="Position.Right" style="opacity: 0" />

限制连接

¥Limiting Connections

你可以通过在 <Handle> 组件上设置 connectable 属性来限制句柄可以拥有的连接数。

¥You can limit the number of connections a handle can have by setting the connectable prop on the <Handle> component.

此属性接受布尔值(默认为 true)、数字(最大连接数)或返回布尔值的函数。

¥This prop accepts a boolean value (defaults to true), a number (the maximum number of connections), or a function that returns a boolean.

使用函数可以实现自定义逻辑来确定是否可以连接句柄。

¥Using a function allows you to implement custom logic to determine if a handle can be connected to or not.

vue
<script lang="ts" setup>
import { Position, Handle, type HandleConnectableFunc } from '@vue-flow/core'  
  
const handleConnectable: HandleConnectableFunc = (node, connectedEdges) => {
  // only allow connections if the node has less than 3 connections
  return connectedEdges.length < 3
}
</script>

<template>
  <Handle type="source" :position="Position.Right" :connectable="handleConnectable" />
</template>

连接模式

¥Connection Mode

默认情况下,Vue Flow 将使用 <VueFlow :connection-mode="ConnectionMode.Loose" />,允许你将边缘连接到任何句柄。这意味着允许 source 和另一个 source 类型 <Handle> 之间的连接。

¥By default, Vue Flow will use <VueFlow :connection-mode="ConnectionMode.Loose" /> which allows you to connect edges to any handle. That means connections between a source and another source type <Handle> are allowed.

如果你想要限制仅在 sourcetarget 类型句柄之间建立连接,可以将 connection-mode 属性设置为 ConnectionMode.Strict

¥If you want to restrict connections to only be made between source and target type handles, you can set the connection-mode prop to ConnectionMode.Strict.

vue
<script setup>
import { ConnectionMode, VueFlow } from '@vue-flow/core'
</script>

<template>
  <VueFlow :connection-mode="ConnectionMode.Strict" />
</template>

动态句柄位置和动态添加/移除句柄

¥Dynamic Handle Positions & Adding/Removing Handles Dynamically

提示

在 Vue Flow 1.x 中,动态添加句柄时无需手动调用 updateNodeInternals。挂载后,句柄会自动尝试附加到节点。但是,如果由于任何原因,情况未按预期发生,你可以遵循以下指南,强制 Vue Flow 更新节点内部结构。

¥In Vue Flow 1.x, there's no need to manually invoke updateNodeInternals when dynamically adding handles. Upon mounting, handles will automatically attempt to attach to the node. However, if for any reason this isn't happening as expected, you can stick to the guideline provided below to enforce Vue Flow to update the node internals.

有时,你可能需要动态修改句柄位置,或者以编程方式向节点添加新的句柄。在这种情况下,Vue Flow API 中的 updateNodeInternals 方法就派上用场了。

¥At times, you may need to modify handle positions dynamically or programmatically add new handles to a node. In this scenario, the updateNodeInternals method found in Vue Flow's API comes in handy.

处理动态句柄时,调用此方法至关重要。否则,节点可能无法识别这些新的句柄,导致边对齐错误。

¥Invoking this method is vital when dealing with dynamic handles. If not, the node might fail to recognize these new handles, resulting in misaligned edges.

updateNodeInternals 函数可以通过以下两种方式之一部署:

¥The updateNodeInternals function can be deployed in one of two ways:

  • 使用存储操作:此方法允许你通过将节点的 ID 传递给方法一次更新多个节点。

    ¥Using the store action: This approach allows you to update several nodes at once by passing their IDs into the method.

  • 从自定义节点组件触发 updateNodeInternals 事件:这不需要传递任何参数。

    ¥Emitting the updateNodeInternals event from your customized node component: This doesn't require any parameters to be passed.

js
import { useVueFlow } from '@vue-flow/core'

const { updateNodeInternals } = useVueFlow()

const onSomeEvent = () => {
  updateNodeInternals(['1'])
}
vue
<script setup>
const emits = defineEmits(['updateNodeInternals'])

const onSomeEvent = () => {
  emits('updateNodeInternals')
}
</script>

VueFlow v1.44 中文网 - 粤ICP备13048890号