1. 为什么你需要Vue3 + jsPlumb?
如果你正在开发一个数据建模工具、一个低代码平台,或者任何需要让用户通过拖拽和连线来建立关系的Web应用,那你肯定遇到过这个核心难题:如何在前端优雅地实现一个可交互的流程图?用户需要能从左边拖一个“用户”节点,右边拖一个“订单”节点,然后在他们之间画一条线,表示“用户创建订单”。
几年前,要实现这个功能,你可能得自己从零开始写一大堆鼠标事件监听、计算连线坐标、处理DOM操作,代码又臭又长还容易出bug。但现在,有了Vue3的响应式系统和jsPlumb这个专门处理连线的库,这件事就变得清晰、可控多了。
我自己在做一个内部数据血缘分析工具时,就选择了这个组合。Vue3的Composition API让逻辑组织非常灵活,而jsPlumb则扛下了所有绘图和交互的脏活累活。简单来说,Vue3负责管理数据和视图状态,jsPlumb负责处理画布上所有“画线”和“拖拽”的物理规则,两者结合,就能快速搭建出专业级的可视化交互场景。
2. 5分钟快速搭建你的第一个连线Demo
光说不练假把式,我们直接动手,用最短的代码让你看到效果。这里假设你已经有了一个Vue3的项目(用Vite或Vue CLI创建的都行)。
2.1 安装与引入
首先,安装jsPlumb库。它没有Vue3的官方封装,我们直接用它的核心库。
npm install --save jsplumb
接下来,在一个Vue组件中,我们引入它。注意,jsPlumb默认导出的是一个对象,我们需要用到里面的 jsPlumb 属性。
<template>
<div>
<h3>我的第一个连线图</h3>
<!-- 容器必须有明确的宽高和相对定位,这是jsPlumb工作的画布 -->
<div id="flow-container"></div>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
// 注意引入方式:jsPlumb库的默认导出是一个对象,其jsPlumb属性才是我们需要的构造函数
import jsPlumb from 'jsplumb';
// 保存jsPlumb实例的引用,后续所有操作都通过它进行
let jsPlumbInstance = null;
onMounted(() => {
initJsPlumb();
});
const initJsPlumb = () => {
// 获取jsPlumb的单例实例,并指定容器
jsPlumbInstance = jsPlumb.jsPlumb.getInstance({
Container: 'flow-container' // 对应上面模板中div的id
});
// 到这里,jsPlumb已经初始化好了,可以开始操作DOM元素了
console.log('jsPlumb实例已创建:', jsPlumbInstance);
};
</script>
<style scoped>
#flow-container {
position: relative; /* 必须设置为relative、absolute或fixed */
width: 800px;
height: 500px;
border: 1px solid #ccc;
margin-top: 20px;
}
</style>
运行起来,打开浏览器控制台,你应该能看到jsPlumb实例被成功打印出来。虽然页面上还什么都没有,但画布的舞台已经搭好了。
2.2 创建可连线的节点
画布有了,我们放两个“盒子”上去,并让他们可以互相连线。我们在模板里直接写两个div,并用jsPlumb的API将它们设置为“源”(可以拖出线)和“目标”(可以接收线)。
<template>
<div>
<h3>我的第一个连线图</h3>
<div id="flow-container">
<!-- 节点A:作为连线的起点 -->
<div id="nodeA" class="flow-node">节点 A</div>
<!-- 节点B:作为连线的终点 -->
<div id="nodeB" class="flow-node">节点 B</div>
</div>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
import jsPlumb from 'jsplumb';
let jsPlumbInstance = null;
onMounted(() => {
initJsPlumb();
});
const initJsPlumb = () => {
jsPlumbInstance = jsPlumb.jsPlumb.getInstance({
Container: 'flow-container'
});
// 使用batch操作,将多个DOM操作打包,提高性能
jsPlumbInstance.batch(() => {
// 将id为nodeA的元素设置为“源”(可以拖出连接线)
jsPlumbInstance.makeSource('nodeA', {
anchor: 'RightMiddle', // 锚点位置:右侧中间
connector: 'Straight', // 连接线类型:直线
maxConnections: -1 // -1表示不限制连接数
});
// 将id为nodeB的元素设置为“目标”(可以接收连接线)
jsPlumbInstance.makeTarget('nodeB', {
anchor: 'LeftMiddle', // 锚点位置:左侧中间
maxConnections: -1
});
// 让两个节点都可以被拖拽
jsPlumbInstance.draggable('nodeA');
jsPlumbInstance.draggable('nodeB');
});
};
</script>
<style scoped>
#flow-container {
position: relative;
width: 800px;
height: 500px;
border: 1px solid #ccc;
margin-top: 20px;
}
.flow-node {
position: absolute;
width: 100px;
height: 60px;
line-height: 60px;
text-align: center;
background-color: #7ec699;
color: white;
border-radius: 4px;
cursor: move;
}
/* 手动设置一下初始位置,方便演示 */
#nodeA {
left: 100px;
top: 100px;
}
#nodeB {
left: 400px;
top: 100px;
}
</style>
现在刷新页面,你应该能看到两个绿色的方块。尝试用鼠标从节点A的右侧边缘拖拽,会拉出一条线;将这条线拖到节点B的左侧边缘松开,一条连接两个节点的直线就画好了!你还可以拖拽这两个节点,连线会自动跟随。是不是很简单?我们只用了几行代码,就实现了一个可交互流程图的核心功能。
3. 构建多列拖拽布局:从静态到动态
上面的例子是静态节点,但实际场景中



被折叠的 条评论
为什么被折叠?



