Vue3 与 AntV X6 节点传参、自动布局及边颜色控制教程

以下是整理后的 AntV X6 + Vue 3 节点开发全流程指南,包含完整代码示例和关键实现细节:

环境搭建与项目初始化

使用 Vite 快速创建 Vue 3 项目:

bash 复制代码
npm create vite@latest x6-vue-demo
cd x6-vue-demo
npm install

安装核心依赖:

bash 复制代码
npm install @antv/x6 @antv/layout @antv/x6-vue-shape element-plus

配置 Element Plus(在 main.js/ts 中):

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

自定义节点组件开发

创建 NodeView.vue 组件:

vue 复制代码
<template>
  <div class="node" @click="handleClick">
    <div class="node-title">{{ nodeData.name }}</div>
    <div class="node-status">状态: {{ nodeData.status || "未执行" }}</div>
  </div>
</template>

<script setup>
import { ref, onBeforeUnmount } from "vue"
const props = defineProps({ getNode: Function })
const node = props.getNode()
const nodeData = ref(node ? node.getData() : {})

const handleChange = ({ current }) => {
  nodeData.value = { ...current }
}
if (node) node.on("change:data", handleChange)

onBeforeUnmount(() => {
  if (node) node.off("change:data", handleChange)
})

const handleClick = () => {
  alert(`点击了: ${nodeData.value.name}`)
}
</script>

<style scoped>
.node {
  width: 120px;
  height: 50px;
  background: #409eff;
  color: #fff;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  cursor: pointer;
}
.node-title { font-weight: bold; }
.node-status { font-size: 10px; margin-top: 4px; }
</style>

主页面实现

创建 GraphDemo.vue 核心逻辑:

vue 复制代码
<template>
  <div>
    <el-button type="primary" @click="setStatus('成功')">父节点成功</el-button>
    <el-button type="danger" @click="setStatus('失败')">父节点失败</el-button>
    <el-button @click="setStatus('等待')">父节点等待</el-button>
    <div class="graph-container" ref="graphRef"></div>
    <TeleportContainer />
  </div>
</template>

<script setup>
import { ref, onMounted, defineComponent } from "vue"
import { Graph } from "@antv/x6"
import { register, getTeleport } from "@antv/x6-vue-shape"
import { DagreLayout } from "@antv/layout"
import NodeView from "../components/NodeView.vue"

const graphRef = ref(null)
let graph = null
const TeleportContainer = defineComponent(getTeleport())

const initGraph = () => {
  register({
    shape: "vue-node",
    component: NodeView,
    getComponentProps(node) {
      return { getNode: () => node }
    }
  })

  graph = new Graph({
    container: graphRef.value,
    background: { color: "#f9f9f9" },
    grid: true
  })

  const taskList = [
    { id: "1", name: "任务A", status: "等待" },
    { id: "2", name: "任务B", status: "等待" },
    { id: "3", name: "任务C", status: "等待" }
  ]

  const relations = [
    { source: "1", target: "2" },
    { source: "1", target: "3" }
  ]

  const nodes = taskList.map((task) => ({
    id: task.id,
    shape: "vue-node",
    width: 120,
    height: 50,
    data: task
  }))

  const edges = relations.map((rel) => ({
    source: rel.source,
    target: rel.target,
    attrs: {
      line: {
        stroke: "#999",
        strokeWidth: 2,
        targetMarker: { name: "classic", width: 12, height: 8 }
      }
    }
  }))

  const layout = new DagreLayout({
    type: "dagre",
    rankdir: "LR",
    nodesep: 40,
    ranksep: 60
  })

  graph.fromJSON(layout.layout({ nodes, edges }))
  updateEdgesColor()
}

const updateEdgesColor = () => {
  graph.getEdges().forEach((edge) => {
    const sourceNode = graph.getCellById(edge.getSourceCellId())
    const status = sourceNode?.getData()?.status || "等待"
    edge.setAttrs({
      line: { 
        stroke: 
          status === "成功" ? "green" :
          status === "失败" ? "red" : "gray"
      }
    })
  })
}

const setStatus = (status) => {
  const parentNode = graph.getCellById("1")
  parentNode.setData({ ...parentNode.getData(), status })
  updateEdgesColor()
}

onMounted(() => initGraph())
</script>

<style scoped>
.graph-container {
  width: 100%;
  height: 500px;
  border: 1px solid #ddd;
  margin-top: 10px;
}
</style>

关键功能说明

自动布局实现

通过 DagreLayout 自动计算节点位置,参数说明:

  • rankdir: "LR" 控制布局方向(Left to Right)
  • nodesep 和 ranksep 控制节点间距

动态边颜色控制
updateEdgesColor 方法根据源节点状态改变连线颜色:

  • 成功状态:绿色边
  • 失败状态:红色边
  • 默认状态:灰色边

节点数据响应式

通过监听 change:data 事件实现节点状态实时更新,注意在组件卸载时移除事件监听

效果说明

运行后可见:

  1. 三个采用自动布局排列的节点
  2. 父节点(任务A)控制两个子节点的边颜色
  3. 点击按钮可切换父节点状态(成功/失败/等待)
  4. 点击节点会显示节点名称提示框
相关推荐
Csvn7 分钟前
性能监控
前端
Highcharts.js9 分钟前
Highcharts Gantt使用符号的自定义数据标签开发甘特图示例
javascript·甘特图·highcharts·图表开发·实战代码·响应式图表
Csvn33 分钟前
构建工具
前端
FRing031 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Java小卷2 小时前
JuanForm vs FormCreate!Vue3 表单引擎联动配置 PK!
vue.js·低代码
kyriewen3 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒4 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫4 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus4 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude
孟陬6 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端