You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JsPlumb社区版在Nuxt/Vue项目中无法动态添加节点和形状问题

解决方案

核心实现思路

动态创建jsPlumb节点只需三步操作:

  • 点击按钮时创建对应样式的DOM节点,插入到jsPlumb绑定的容器中
  • 调用jsPlumb实例的manage方法,将DOM节点注册为可拖拽的jsPlumb节点
  • 给节点添加连接端点,方便后续连线使用

完整修改后代码

<template>
  <div>
    <div class="container-fluid">
      <div class="row">
        <div class="col-md-6">
          <button class="btn btn-primary btn-sm" @click="addConnector">
            Add Connector
          </button>&nbsp;
          <button class="btn btn-primary btn-sm" @click="addNode">
            Add Event
          </button>&nbsp;
          <button class="btn btn-success btn-sm" @click="submitEvents">
            Submit
          </button>&nbsp;
        </div>
      </div>
      <div class="row">
        <div class="col-md-12">
          <div id="diagram" ref="diagram" style="position: relative; width:100%; height:800px;border:1px solid #eee;" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
let jsPlumb = null

export default {
  data () {
    return {
      nodeCounter: 0,
      nodeArray: [],
      connectorCounter: 0,
      connectorArray: [],
      allEventsInfoArray: []
    }
  },
  async mounted () {
    if (process.browser) {
      const jsPlumbBrowserUI = await import('@jsplumb/browser-ui')

      jsPlumb = jsPlumbBrowserUI.newInstance({
        dragOptions: {
          cursor: 'pointer',
          zIndex: 2000
        },
        container: this.$refs.diagram
      })
      // 全局默认端点配置,避免每个节点重复写
      jsPlumb.addEndpointSpec({
        endpoint: 'Dot',
        anchor: 'AutoDefault',
        maxConnections: -1 // 不限制连接数
      })
    }
  },
  methods: {
    addNode () {
      this.nodeCounter++
      const nodeId = `node_${this.nodeCounter}`
      // 1. 创建节点DOM
      const nodeEl = document.createElement('div')
      nodeEl.id = nodeId
      nodeEl.className = 'flow-node'
      nodeEl.innerText = `节点${this.nodeCounter}`
      // 设置初始位置,每次新增偏移20px避免重叠
      nodeEl.style.left = `${100 + this.nodeCounter * 20}px`
      nodeEl.style.top = `${100 + this.nodeCounter * 20}px`
      // 2. 插入到画布容器
      this.$refs.diagram.appendChild(nodeEl)
      // 3. 注册为jsPlumb可拖拽节点
      jsPlumb.manage(nodeEl)
      // 4. 给节点添加上下左右四个连接端点
      ['Top', 'Right', 'Bottom', 'Left'].forEach(anchor => {
        jsPlumb.addEndpoint(nodeId, { anchor })
      })
      // 保存节点信息方便后续处理
      this.nodeArray.push({
        id: nodeId,
        el: nodeEl
      })
    },
    addConnector () {
      // connect方法必须指定source和target参数,示例默认连接最后两个节点,可按需改为选中节点再连线的逻辑
      if (this.nodeArray.length < 2) return alert('至少需要2个节点才能创建连线')
      jsPlumb.connect({
        source: this.nodeArray[this.nodeArray.length - 2].id,
        target: this.nodeArray[this.nodeArray.length - 1].id,
        anchor: 'AutoDefault',
        endpoints: ['Dot', 'Blank'],
        overlays: [
          { type: 'Arrow', options: { location: 1 } },
          {
            type: 'Label',
            options: { label: 'foo', location: 0.25, id: `label_${this.connectorCounter++}` }
          }
        ]
      })
    },
    submitEvents () {
      // 提交逻辑可自行获取jsPlumb实例的连接、节点信息
      console.log('所有节点:', this.nodeArray)
      console.log('所有连线:', jsPlumb.getConnections())
    }
  }
}
</script>

<style scoped>
.flow-node {
  position: absolute;
  width: 120px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border: 1px solid #2d8cf0;
  background: #e8f3ff;
  border-radius: 4px;
  cursor: move;
}
/* style加了scoped时需要用深度选择器覆盖jsPlumb默认样式 */
:deep(.jtk-endpoint) {
  width: 10px;
  height: 10px;
  background: #2d8cf0;
}
:deep(.jtk-connector) {
  stroke: #2d8cf0;
  stroke-width: 2;
}
</style>

注意事项

  • 示例给diagram容器加了固定高度和边框,避免画布高度为0看不见节点,可按需调整
  • 新增节点的初始位置是按序号偏移的,可改成固定位置或者鼠标点击位置生成
  • addConnector方法默认连接最后两个节点,实际使用时可以改成用户点击选中两个节点再连线的逻辑

内容的提问来源于stack exchange,提问作者BATMAN_2008

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 19:36:04