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

张开发
2026/4/3 23:53:05 15 分钟阅读
实战-自定义列表组件节点创建任意连接桩
在真实的项目中经常有各种各样的自定义组件节点并且需要创建连线这个时候就需要用到连接桩了。如下就是一种常用的真实需求场景那么针对这种自定义组件节点如何有规则的创建出连接桩了完整的table组件节点代码如下template div classtable-wrapper refwtNode el-table :datadataList border stylewidth: 100% :row-class-namegetRowClassName el-table-column fixed propname label姓名 /el-table-column el-table-column propage label年龄 /el-table-column el-table-column propgender label性别 /el-table-columnF el-table-column fixedright label操作 width100 template slot-scopescope el-button typetext sizesmall clickhandleDelete(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. 左右连接桩X0 和 X1 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 langscss .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

更多文章