Skip to content

边简介

¥Introduction to Edges

边是连接节点的链接,形成一个地图。每条边从一个句柄延伸到另一个句柄,可以根据你的喜好进行自定义。

¥Edges are the links connecting your nodes, forming a map. Each edge runs from one handle to another, and can be customized to your liking.

请记住,每条边都是唯一的,因此需要一个唯一的 ID、一个源节点 ID 和一个目标节点 ID。

¥Remember, every edge is unique and thus requires a unique id, a source and target node id.

有关边可用选项的完整列表,请查看 边缘类型

¥For the full list of options available for an edge, check out the Edge Type.

向图中添加边

¥Adding Edges to the Graph

边的渲染是通过将它们传递给 Vue Flow 组件的 edges 属性(或已弃用的 v-model 属性)来实现的。

¥Edges are rendered by passing them to the edges prop (or the deprecated v-model prop) of the Vue Flow component.

警告

此方法不会创建更改。查看 受控流程 部分了解更多信息。

¥This method will not create a change. Check out the Controlled Flow section for more information.

vue

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

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  }
]);

const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  }
]);
</script>

<template>
  

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

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { Node, Edge } from '@vue-flow/core'
import { VueFlow } from '@vue-flow/core'

const nodes = ref<Node[]>([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  }
]);

const edges = ref<Edge[]>([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  }
]);
</script>

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

If you are working with more complex graphs or simply require access to the internal state, the useVueFlow composable will come in handy.

The addEdges action is available through useVueFlow, allowing you to add edges straight to the state.

What's more, this action isn't limited to the component rendering the graph; it can be utilized elsewhere, like in a Sidebar or Toolbar.

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

const initialNodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  }
])

const { addEdges } = useVueFlow()

addEdges([
  {
    source: '1',
    target: '2',

    // if a node has multiple handles of the same type,
    // you should specify which handle to use by id
    sourceHandle: null,
    targetHandle: null,
  }
])
</script>

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

Removing Edges from the Graph

Similar to adding edges, edges can be removed from the graph by removing them from the mode-value (using v-model) or from the edges prop of the Vue Flow component.

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

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
]);

const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  }
]);

function removeEdge(id) {
  edges.value = edges.value.filter((edge) => edge.id !== id)
}
</script>

<template>
  <VueFlow :nodes="nodes" :edges="edges">
    <Panel>
      <button @click="removeEdge('e1->2')">Remove Edge</button>
    </Panel>
  </VueFlow>


</template>

removeEdges 操作可通过 useVueFlow 获得,允许你直接从状态中删除边。

¥The removeEdges action is available through useVueFlow, allowing you to remove edges straight from the state.

你还可以在渲染图表的组件外部使用此操作,例如在侧边栏或工具栏中。

¥You can also use this action outside the component rendering the graph, like in a Sidebar or Toolbar.

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

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
  {
    id: '3',
    position: { x: 250, y: 50 },
    data: { label: 'Node 3', },
  },
  {
    id: '4',
    position: { x: 250, y: 250 },
    data: { label: 'Node 4', },
  },
])

const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  },
  {
    id: 'e1->3',
    source: '1',
    target: '3',
  },
  {
    id: 'e2->3',
    source: '2',
    target: '3',
  },
  {
    id: 'e2->4',
    source: '2',
    target: '4',
  },
])

const { removeEdges } = useVueFlow()

function removeOneEdge() {
  removeEdges('e1->2')
}

function removeMultipleEdges() {
  removeEdges(['e1->3', 'e2->3'])
}
</script>

<template>
  

<VueFlow :nodes="nodes" :edges="edges">
    <Panel>
      <button @click="removeOneEdge">Remove Edge 1</button>
      <button @click="removeMultipleEdges">Remove Edges 2 and 3</button>
    </Panel>
  </VueFlow>


</template>

更新边数据

¥Updating Edge Data

由于边是响应式对象,你可以随时通过简单地改变它来更新它们的数据。这允许你随时更改标签,甚至向数据对象添加新属性。

¥Since edges are reactive object, you can update their data at any point by simply mutating it. This allows you to change the label, or even add new properties to the data object at any point in time.

实现此目的的方法有很多,以下是一些示例:

¥There are multiple ways of achieving this, here are some examples:

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

const instance = useVueFlow()

// use the `updateEdgeData` method to update the data of an edge
instance.updateEdgeData(edgeId, { hello: 'mona' })

// find the edge in the state by its id
const edge = instance.findEdge(edgeId)

edge.data = {
  ...edge.data,
  hello: 'world',
}

// you can also mutate properties like `selectable` or `animated`
edge.selectable = !edge.selectable
edge.animated = !edge.animated
vue
<!-- CustomEdge.vue -->
<script setup>
import { useEdge } from '@vue-flow/core'

// `useEdge` returns us the edge object straight from the state
// since the edge obj is reactive, we can mutate it to update our edges' data
const { edge } = useEdge()

function onSomeEvent() {
  edge.data = {
    ...edge.data,  
    hello: 'world',
  }
  
  // you can also mutate properties like `selectable` or `animated`
  edge.selectable = !edge.selectable
  edge.animated = !edge.animated
}
</script>
vue
<script setup>
import { ref } from 'vue'

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: {
      label: 'Node 1',
      hello: 'world',
    },
  },
  {
      id: '2',
      position: { x: 50, y: 250 },
      data: { label: 'Node 2', },
  },
])

const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  },
])

function onSomeEvent(edgeId) {
  const edge = edges.value.find((edge) => edge.id === edgeId)
  edge.data = {
    ...elements.value[0].data,
    hello: 'world',
  }

  // you can also mutate properties like `selectable` or `animated`
  edge.selectable = !edge.selectable
  edge.animated = !edge.animated
}
</script>

<template>
  

<VueFlow v-model="elements" />
</template>
```

Predefined Edge-Types

Vue Flow provides several built-in edge types that you can leverage immediately. The included node types are default (bezier), step, smoothstep and straight.

Default Edge (Bezier)

The default edge is a bezier curve that connects two nodes.

Step Edge

A step edge has a straight path with a step towards the target.

Smoothstep Edge

The same as the step edge though with a border radius on the step (rounded step).

Straight Edge

A simple straight path.

User-Defined Edges

On top of the default edge types mentioned earlier, you can create as many custom edge-types as you need. Edge-types are determined from your edges' definitions.

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

import CustomEdge from './CustomEdge.vue'
import SpecialEdge from './SpecialEdge.vue'

export const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
    // this will create the edge-type `custom`
    type: 'custom',
  },
  {
    id: 'e1->3',
    source: '1',
    target: '3',
    // this will create the edge-type `special`
    type: 'special',
  }
])
  
const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
  {
    id: '3',
    position: { x: 250, y: 50 },
    data: { label: 'Node 3', },
  },
  {
    id: '4',
    position: { x: 250, y: 250 },
    data: { label: 'Node 4', },
  },
])
</script>

<template>
  

<VueFlow :nodes="nodes" :edges="edges">
    <template #edge-custom="customEdgeProps">
      <CustomEdge v-bind="customEdgeProps" />
    </template>
    
    <template #edge-special="specialEdgeProps">
      <SpecialEdge v-bind="specialEdgeProps" />
    </template>
  </VueFlow>


</template>
vue
<script setup>
import { BezierEdge } from '@vue-flow/core';

// props were passed from the slot using `v-bind="customEdgeProps"`
const props = defineProps(['sourceX', 'sourceY', 'targetX', 'targetY', 'sourcePosition', 'targetPosition']);
</script>

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

<template>
  <BezierEdge
      :source-x="sourceX"
      :source-y="sourceY"
      :target-x="targetX"
      :target-y="targetY"
      :source-position="sourcePosition"
      :target-position="targetPosition"
  />
</template>
vue
<script setup lang="ts">
import { ref } from 'vue'
import type { Edge } from '@vue-flow/core'
import { VueFlow } from '@vue-flow/core'

import CustomEdge from './CustomEdge.vue'
import SpecialEdge from './SpecialEdge.vue'

// You can pass 3 optional generic arguments to the Edge type, allowing you to define:
// 1. The data object type
// 2. The events object type
// 3. The possible edge types

interface CustomData {
    hello: string
}

type CustomEdgeTypes = 'custom' | 'special'

type CustomEdge = Edge<CustomData, any, CustomEdgeTypes>

export const edges = ref<CustomEdge[]>([
    {
      id: 'e1-2',
      source: '1',
      target: '2',
      // this will create the edge-type `custom`
      type: 'custom',
    },
    {
      id: 'e1-3',
      source: '1',
      target: '3',
      // this will create the edge-type `special`
      type: 'special',
    },
    
    {
      id: 'e1-4',
      source: '1',
      target: '4',
      // this will throw a type error, as the type is not defined in the CustomEdgeTypes
      // regardless it would be rendered as a default edge type
      type: 'not-defined',
    }
])
  
const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
  {
    id: '3',
    position: { x: 250, y: 50 },
    data: { label: 'Node 3', },
  },
  {
    id: '4',
    position: { x: 250, y: 250 },
    data: { label: 'Node 4', },
  },
])  
</script>

<template>
  

<VueFlow :nodes="nodes" :edges="edges">
    <template #edge-custom="customEdgeProps">
      <CustomEdge v-bind="customEdgeProps" />
    </template>
    
    <template #edge-special="specialEdgeProps">
      <SpecialEdge v-bind="specialEdgeProps" />
    </template>
  </VueFlow>


</template>
vue
<script setup lang="ts">
import type { EdgeProps } from '@vue-flow/core';
import { BezierEdge } from '@vue-flow/core';

import { CustomData } from './edges'

// props were passed from the slot using `v-bind="customEdgeProps"`
const props = defineProps<EdgeProps<CustomData>>();

console.log(props.data.hello) // 'world'
</script>

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

<template>
  <BezierEdge
      :source-x="sourceX"
      :source-y="sourceY"
      :target-x="targetX"
      :target-y="targetY"
      :source-position="sourcePosition"
      :target-position="targetPosition"
  />
</template>

然后,Vue Flow 将尝试将此边类型解析为组件。优先考虑状态的 edgeTypes 对象中的定义。接下来,它会尝试将该组件与全局注册的同名组件进行匹配。最后,它会搜索提供的模板插槽来填充边类型。

¥Vue Flow will then attempt to resolve this edge-type to a component. Priority is given to a definition in the edgeTypes object of the state. Next, it tries to match the component to a globally registered one with the same name. Finally, it searches for a provided template slot to fill in the edge-type.

如果在解析组件时没有任何方法产生结果,则使用默认边类型作为后备。

¥If no methods produce a result in resolving the component, the default edge-type is used as a fallback.

模板插槽

¥Template slots

定义自定义边最简单的方法之一是将它们作为模板插槽传递。针对用户定义的边类型,已完成对插槽名称的动态解析,这意味着类型为 custom 的边预计会有一个名为 #edge-custom 的插槽。

¥One of the easiest ways to define custom edges is, by passing them as template slots. Dynamic resolution to slot-names is done for your user-defined edge-types, meaning a edge with the type custom is expected to have a slot named #edge-custom.

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

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
])

const edges = ref([
  {
    id: 'e1->2',
    type: 'custom',
    source: '1',
    target: '2',
  },
])
</script>

<template>
  

<VueFlow :nodes="nodes" :edges="edges">
    <template #edge-custom="props">
      <CustomEdge v-bind="props" />
    </template>
  </VueFlow>


</template>

边缘类型对象

¥Edge-types object

或者,也可以通过将对象作为 prop 传递给 VueFlow 组件(或作为可组合项的选项)来定义边缘类型。

¥Alternatively, edge-types can also be defined by passing an object as a prop to the VueFlow component (or as an option to the composable).

警告

请谨慎地将你的组件标记为原始(使用 Vue 库中的 marked 函数),以防止它们转换为响应式对象。否则,Vue 将在控制台上显示警告。

¥Take precaution to mark your components as raw (utilizing the marked function from the Vue library) to prevent their conversion into reactive objects. Otherwise, Vue will display a warning on the console.

vue
<script setup>
import { markRaw } from 'vue'
import CustomEdge from './CustomEdge.vue'

const edgeTypes = {
  custom: markRaw(CustomEdge),
}

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
])

const edges = ref([
  {
    id: 'e1->2',
    type: 'custom',
    source: '1',
    target: '2',
  },
])
</script>
<template>
  

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

Edge Props

Your custom edges are enclosed so that fundamental functions like selecting operate. But you may wish to expand on these features or implement your business logic inside edges, thus your edges receive the following properties:

Prop NameDescriptionTypeOptional
idUnique edge idstring
sourceNodeThe originating nodeGraphNode
targetNodeThe destination nodeGraphNode
sourceID of the source nodestring
targetID of the target nodestring
typeEdge Typestring
labelEdge label, can be a string or a VNodestring | VNode | Component | Object
styleCSS propertiesCSSProperties
selectedIs edge selectedboolean
sourcePositionSource positionPosition
targetPositionTarget positionPosition
sourceHandleIdID of the source handlestring
targetHandleIdID of the target handlestring
animatedIs edge animatedboolean
updatableIs edge updatableboolean
markerStartStart markerstring
markerEndEnd markerstring
curvatureThe curvature of the edgenumber
interactionWidthWidth of the interaction area for the edgenumber
dataAdditional data of edgeany object
eventsContextual and custom events of edgeEdgeEventsOn

Edge Events

Vue Flow provides two main ways of listening to edge events, either by using useVueFlow to bind listeners to the event handlers or by binding them to the <VueFlow> component.

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

// useVueFlow provides access to the event handlers
const { 
  onEdgeClick,
  onEdgeDoubleClick,
  onEdgeContextMenu,
  onEdgeMouseEnter,
  onEdgeMouseLeave,
  onEdgeMouseMove,
  onEdgeUpdateStart,
  onEdgeUpdate,
  onEdgeUpdateEnd,
} = useVueFlow()
  
const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
])

const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  },
])
  
// bind listeners to the event handlers
onEdgeClick((event, edge) => {
  console.log('edge clicked', edge)
})

onEdgeDoubleClick((event, edge) => {
  console.log('edge double clicked', edge)
})

onEdgeContextMenu((event, edge) => {
  console.log('edge context menu', edge)
})
  
// ... and so on  
</script>

<template>
  <VueFlow :nodes="nodes" :edges="edges" />
</template>
vue
<script setup>
import { ref } from 'vue'
import { VueFlow } from '@vue-flow/core'

const nodes = ref([
  {
    id: '1',
    position: { x: 50, y: 50 },
    data: { label: 'Node 1', },
  },
  {
    id: '2',
    position: { x: 50, y: 250 },
    data: { label: 'Node 2', },
  },
])

const edges = ref([
  {
    id: 'e1->2',
    source: '1',
    target: '2',
  },
])
  
function logEvent(eventName, data) {
  console.log(eventName, data)
}
</script>

<template>
  <VueFlow
    :nodes="nodes"
    :edges="edges"
    @edge-click="logEvent('edge clicked', $event)"
    @edge-double-click="logEvent('edge double clicked', $event)"
    @edge-context-menu="logEvent('edge context menu', $event)"
    @edge-mouse-enter="logEvent('edge mouse enter', $event)"
    @edge-mouse-leave="logEvent('edge mouse leave', $event)"
    @edge-mouse-move="logEvent('edge mouse move', $event)"
    @edge-update-start="logEvent('edge update start', $event)"
    @edge-update="logEvent('edge update', $event)"
    @edge-update-end="logEvent('edge update end', $event)"
  />
</template>

Interact to see events in browser console

<Background class="rounded-lg" />

Customizing Appearance

TIP

To override the styles of the default theme, visit the Theming section.

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