当前位置: 首页 > news >正文

实战-自定义列表组件节点创建任意连接桩

在真实的项目中,经常有各种各样的自定义组件节点,并且需要创建连线,这个时候就需要用到连接桩了。如下,就是一种常用的真实需求场景:

那么针对这种自定义组件节点,如何有规则的创建出连接桩了?

完整的table组件节点代码如下:
<template> <div class="table-wrapper" ref="wtNode"> <el-table :data="dataList" border style="width: 100%" :row-class-name="getRowClassName" > <el-table-column fixed prop="name" label="姓名"> </el-table-column> <el-table-column prop="age" label="年龄"> </el-table-column> <el-table-column prop="gender" label="性别"> </el-table-column>F <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button type="text" size="small" @click="handleDelete(scope.row)" >删除</el-button > </template> </el-table-column> </el-table> </div> </template> <script> export default { components: {}, inject: ['getNode', 'getGraph'], props: {}, data() { return { dataList: [] } }, computed: {}, watch: {}, created() {}, mounted() { this.init() }, beforeDestroy() {}, methods: { init() { this.graph = this.getGraph() this.node = this.getNode() this.node.$ = { vueComponent: this // 将当前 Vue 组件实例绑定到 node.$ 上 } const dataList = this.graph.userData.dataList || [] this.dataList = dataList this.$nextTick(() => { this.setNodeSize() }) }, setNodeSize() { const { width, height } = this.$refs.wtNode.getBoundingClientRect() this.node.size(width, height) }, /** * 一次性创建所有连接桩(左、中、右) */ addAllPorts() { // 1. 先移除旧端口,防止重复 this.node.removePorts() const nodeEl = this.$refs.wtNode // 获取表格容器的高度,用于计算相对 Y 坐标 const parentRect = nodeEl.getBoundingClientRect() // 2. 获取所有行 const liArr = nodeEl.querySelectorAll( '.el-table__body-wrapper .el-table__row' ) liArr.forEach(li => { const className = li.className // 提取 ID (对应 getRowClassName 中的逻辑) const match = className.match(/row-id-(\S+)/) if (!match) return // 防止获取失败报错 const rowId = match[1] const liRect = li.getBoundingClientRect() // 3. 计算垂直中心 Y (相对节点的高度百分比) const centerY = (liRect.top - parentRect.top + liRect.height / 2) / parentRect.height // 4. 同时添加左、中、右 三个端口 const ports = [ { id: `${rowId}-left`, // 唯一 ID group: 'absolute', args: { x: '0%', y: centerY } // 左侧 }, { id: `${rowId}-center`, // 唯一 ID group: 'absolute', args: { x: '50%', y: centerY } // 中间 }, { id: `${rowId}-right`, // 唯一 ID group: 'absolute', args: { x: '100%', y: centerY } // 右侧 } ] // 5. 批量添加 ports.forEach(port => this.node.addPort(port)) }) }, // 创建左侧连接桩 addLeftPorts() { this.addPorts('0') }, // 创建右侧连接桩 addRightPorts() { this.addPorts('100') }, // 创建中间连接桩 addCenterPorts() { this.addPorts('50') }, /** * 创建连接桩 * @param {*} position 连接桩位置(0-100) * @returns */ addPorts(position) { this.node.removePorts() const nodeEl = this.$refs.wtNode const parentRect = nodeEl.getBoundingClientRect() // 安全:只用于内部相对计算 const liArr = nodeEl.querySelectorAll( '.el-table__body-wrapper .el-table__row' ) liArr.forEach(li => { const className = li.className // 简单处理获取 id const rowId = className.split('row-id-')[1] const liRect = li.getBoundingClientRect() // 整行垂直中心 Y(用于 left / right / number 三个 port) const centerY = (liRect.top - parentRect.top + liRect.height / 2) / parentRect.height // 1. 左右连接桩(X=0 和 X=1) this.node.addPort({ id: rowId + '-center', group: 'absolute', args: { x: position + '%', y: centerY } }) }) }, handleDelete(row) { const index = this.dataList.indexOf(row) if (index !== -1) { this.dataList.splice(index, 1) } }, getRowClassName({ row }) { return `row-id-${row.id}` } } } </script> <style scoped lang="scss"> .table-wrapper { ::v-deep .el-table .el-table__cell { padding: 5px 0; } } </style>
核心代码说明

页面调用
// 创建左侧连接桩 addLeftPorts() { this.node.$.vueComponent.addPorts('0') }, // 创建右侧连接桩 addRightPorts() { this.node.$.vueComponent.addPorts('100') }, // 创建中间连接桩 addCenterPorts() { this.node.$.vueComponent.addPorts('50') }, addHorizontalPorts() { this.node.$.vueComponent.addPorts(this.value1) }
总结

其中关键的代码就是,如下:

const liRect = li.getBoundingClientRect() // 整行垂直中心 Y(用于 left / right / number 三个 port) const centerY = (liRect.top - parentRect.top + liRect.height / 2) / parentRect.height
http://www.jsqmd.com/news/578361/

相关文章:

  • LBM格子玻尔兹曼方法模拟圆柱扰流及升阻力系数对比
  • UWB定位算法避坑指南:如何避免常见错误并提升定位精度(含2025最新优化技巧)
  • 人工智能之语音领域 语音处理 第三章 语音特征提取与表示学习
  • OpenClaw:GitHub4个月暴涨18万星!一人开发的AI助手,竟要重构你的未来?
  • OpenClaw安全实践:千问3.5-9B本地化部署方案
  • DLSS Swapper:5分钟让游戏性能飞升的智能管家
  • 生成指定长度的随机验证码,并让用户输入验证码进行验证:
  • 《学习Java的第十一天》
  • 在项目管理的过程中,如何自动分配资源作为任务负责人?
  • SEO_避开常见误区,正确理解SEO的核心价值(127 )
  • FA-XGBoost数据分类预测:基于交叉验证的参数优化Matlab代码
  • GLM-4.1V-9B-Base多场景:教育题图解析、法律文书图示理解、科研图表解读
  • 人流后生殖健康修护:科学方案与行业洞察
  • docker挂载vscode之后的打开步骤
  • React状态管理新范式:3种方案对比与选型建议
  • 利用快马平台快速构建node.js express api原型,十分钟搭建可运行后端服务
  • 新手避坑指南:用Selenium和MongoDB爬取东方财富股吧评论(附完整代码)
  • 利用快马平台快速构建openclaw本地部署原型,十分钟搞定环境配置
  • 1.QQ退出后,浏览器仍然能打开空间?2.它是用什么语言开发的?
  • 基于Matlab的自适应信号滤波降噪:心音信号处理之旅
  • AI深度学习中的张量的类型转换
  • 2026年 北京保密资质认定推荐榜单:一级/二级科研生产保密资格,专业高效合规认证服务公司精选 - 品牌企业推荐师(官方)
  • 互联网大厂Java求职面试丨技术点全覆盖的面试问答实战
  • 技术赋能B端拓客:号码核验行业的迭代与价值升级氪迹科技法人股东号码筛选系统,阶梯式价格
  • Claude Code代码泄露第二天,Anthropic 把最骚的功能悄悄上线了。
  • 智谱 GLM-5.1 正式发布:华为芯片训练的开源模型编码能力达 Claude Opus 4.6 的 94.6%
  • ESP芯片全流程烧录利器:esptool开源工具高效应用指南
  • 新手零基础入门:利用快马平台交互式学习Python库安装与初体验
  • 商城小程序开发公司哪家值得选:五大平台深度对比 - 企业数字化改造和转型
  • Go微服务缓存策略:4种方案解决热点数据击穿问题