Skip to content

可组合项

🌐 Composables

useVueFlow

useVueFlow 可组合函数为你提供了一组与图表互动的方法。

🌐 The useVueFlow composable provides you with a set of methods to interact with the graph.

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

const { onInit, findNode, fitView, snapToGrid } = useVueFlow()

const nodes = ref([/* ... */])

const edges = ref([/* ... */])

// to enable snapping to grid
snapToGrid.value = true

// any event that is emitted from the `<VueFlow />` component can be listened to using the `onEventName` method
onInit((instance) => {
  // `instance` is the same type as the return of `useVueFlow` (VueFlowStore)
  
  fitView()
  
  const node = findNode('1')
  
  if (node) {
    node.position = { x: 100, y: 100 }
  }
})
</script>

<template>
  <VueFlow :nodes="nodes" :edges="edges" />
</template>

useVueFlow 会暴露整个内部状态,包括节点和边。 这些值是响应式的,这意味着更改从 useVueFlow 返回的值会触发图的变化。

状态创建和注入

🌐 State creation and injection

useVueFlow 可组合函数在第一次调用时会创建一个新的 VueFlowStore 实例,并将其注入到 Vue 组件树中。这允许你在任何子组件中使用 useVueFlow 可组合函数访问该 store。

🌐 The useVueFlow composable creates, on first call, a new instance of the VueFlowStore and injects it into the Vue component tree. This allows you to access the store from any child component using the useVueFlow composable.

这也意味着 useVueFlow第一次调用至关重要,因为它决定了将在整个组件树中使用的状态实例。 你可以把它看作一种类似 <VueFlowProvider> 的封装器,会自动注入到组件树中。

🌐 This also means that the first call of useVueFlow is crucial as it determines the state instance that will be used throughout the component tree. You can think of it as a sort of <VueFlowProvider> wrapper that is automatically injected into the component tree.

你可以在指南的状态部分中阅读更多内容。

🌐 You can read more about this in the State section of the guide.

强制执行特定状态实例

🌐 Enforcing a specific state instance

如果有必要,你可以通过向 useVueFlow 可组合函数传递一个 id 来强制使用特定的状态实例。

🌐 If necessary, you can enforce the use of a specific state instance by passing an id to the useVueFlow composable.

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

const { onInit } = useVueFlow({ id: 'my-flow-instance' })

onInit((instance) => {
  // `instance` is the same type as the return of `useVueFlow` (VueFlowStore)
})

useHandleConnections

useHandleConnections 为你提供了连接到特定 <Handle> 的一系列连接。

ts
import { type HandleConnection, useHandleConnections } from '@vue-flow/core'

// get all connections where this node is the target (incoming connections)
const targetConnections = useHandleConnections({
  // type is required
  type: 'target',
})

// get all connections where this node is the source (outgoing connections)
const sourceConnections = useHandleConnections({
  type: 'source',
})

const connections = useHandleConnections({
  id: 'handle-1', // you can explicitly pass a handle id if there are multiple handles of the same type
  nodeId: '1', // you can explicitly pass a node id, otherwise it's used from the `NodeId  injection
  type: 'target',
  onConnect: (connections: HandleConnection[]) => {
    // do something with the connections
  },
  onDisconnect: (connections: HandleConnection[]) => {
    // do something with the connections
  },
})

useNodeConnections

useNodeConnections 为你提供了与特定节点相连接的连接数组。这个可组合函数在你想获取某个节点的所有连接(无论是 source 类型还是 target 类型)时尤其有用。

ts
import { type HandleConnection, useNodeConnections } from '@vue-flow/core'

// get all connections where this node is the target (incoming connections)
const targetConnections = useNodeConnections({
  // type is required
  handleType: 'target',
})

// get all connections where this node is the source (outgoing connections)
const sourceConnections = useNodeConnections({
  handleType: 'source',
})

const handleConnections = useNodeConnections({
  handleId: 'handle-1', // you can explicitly pass a handle id if you want to get connections of a specific handle
})

const connections = useNodeConnections({
  nodeId: '1', // you can explicitly pass a node id, otherwise it's used from the `NodeId  injection
  handleType: 'target',
  onConnect: (connections: HandleConnection[]) => {
    // do something with the connections
  },
  onDisconnect: (connections: HandleConnection[]) => {
    // do something with the connections
  },
})

useNodesData

useNodesData 根据你传入的节点 ID 为你提供一组数据对象。 它在与 useHandleConnections 一起使用时尤其有用。

ts
import { useNodesData, useHandleConnections } from '@vue-flow/core'

// get all connections where this node is the target (incoming connections)
const connections = useHandleConnections({
  type: 'target',
})

const data = useNodesData(() => connections.value.map((connection) => connection.source))

console.log(data.value) // [{ /* ... */]

为了进一步缩小返回数据的类型,可以传递一个保护函数作为第二个参数。

🌐 To further narrow down the type of the returned data, you can pass a guard function as the 2nd argument.

ts
import { useNodesData, useHandleConnections, type Node } from '@vue-flow/core'

type MyNode = Node<{ foo: string }>

const connections = useHandleConnections({
  type: 'target',
})

const data = useNodesData(() => connections.value.map((connection) => connection.source), (node): node is MyNode => node.type === 'foo')

console.log(data.value) // [{ /* foo: string */]

useNodeId

useNodeId 为你提供当前节点 ID。

这个可组合函数应该在自定义节点组件内部调用,因为节点的 ID 是由内部的 <NodeWrapper /> 组件提供的。

🌐 This composable should be called inside a custom node component, as the id for the node is provided by the internal <NodeWrapper /> component.

ts
import { useNodeId } from '@vue-flow/core'

const nodeId = useNodeId()

console.log(nodeId.value) // '1'

useHandle

除了使用 Handle 组件之外,你还可以使用 useHandle 可组合组件来创建自己的自定义节点。

🌐 Instead of using the Handle component you can use the useHandle composable to create your own custom nodes.

useHandle 为你提供了 pointerDown 和 click 处理函数,你可以将它们应用到你想用作节点操作的元素上。

默认句柄组件的构建方式如下:

🌐 This is how the default handle component is built:

vue

<script lang="ts" setup>
import { NodeId, useHandle, useVueFlow } from '@vue-flow/core'
import type { HandleProps, Position } from '@vue-flow/core'

const props = withDefaults(defineProps<HandleProps>(), {
  type: 'source',
  position: 'top' as Position,
  connectable: true,
})

const nodeId = inject(NodeId, '')

const { id, hooks, connectionStartHandle } = useVueFlow()

const { handlePointerDown, handleClick } = useHandle({
  nodeId,
  handleId: props.id,
  isValidConnection: props.isValidConnection,
  type: props.type,
})

const onMouseDownHandler = (event: MouseEvent) => handlePointerDown(event)

const onClickHandler = (event: MouseEvent) => handleClick(event)
</script>

<script lang="ts">
export default {
  name: 'CustomHandle',
}
</script>

<template>
  <div
    :data-handleid="id"
    :data-nodeid="nodeId"
    :data-handlepos="position"
    class="vue-flow__handle nodrag"
    :class="[
      `vue-flow__handle-${position}`,
      `vue-flow__handle-${id}`,
      {
        source: type !== 'target',
        target: type === 'target',
        connectable: connectable,
        connecting:
          connectionStartHandle?.nodeId === nodeId &&
          connectionStartHandle?.handleId === id &&
          connectionStartHandle?.type === type,
      },
    ]"
    @mousedown="onMouseDownHandler"
    @click="onClickHandler"
  >
    <slot :node-id="nodeId" v-bind="props"></slot>
  </div>
</template>

VueFlow 中文网 - 粤ICP备13048890号