Vue3 + vue-draggable-plus 实现可拖拽的数据源选择面板
在前端开发中,拖拽交互 是一个非常常见的功能场景,比如 报表字段选择、仪表盘组件布局、数据源筛选 等。最近我在一个项目中需要实现这样的功能:
-
左侧展示一组可选的数据源;
-
用户可以通过拖拽的方式将其放入右侧的不同分组(实时状态、累计数据、性能指标);
-
已经拖入的项目不能再次重复拖拽;
-
每个分组支持删除恢复,删除后左侧数据源重新可用;
-
拖拽过程带有平滑动画。
本文将基于 Vue3 + vue-draggable-plus +Ant Design Vue 来实现这一功能,并且逐步讲解关键点。
一、效果展示
实现后的交互效果如下图所示:
二、主要技术栈
-
Vue3 +
<script setup>
:组合式 API 写法,语法更简洁; -
Ant Design Vue:提供页面布局(Row/Col)、空状态、图标等 UI 组件;
-
vue-draggable-plus:基于
SortableJS
封装的 Vue3 拖拽库,功能强大且文档完善;
📚 中文文档导引:
👉 vue-draggable-plus 官方文档(中文)
如果你第一次接触这个库,建议先快速浏览一遍官方文档,里面对 group、clone、animation 等核心配置都有详细解释。
安装依赖:
npm install ant-design-vue vue-draggable-plus @ant-design/icons-vue
三、核心代码实现
1. 数据源定义
左侧的数据源 availableDataSource
定义了一些模拟数据:
interface AvailableDataSource {id: numberdataName: stringbuildStr: string
}const availableDataSource = ref<AvailableDataSource[]>([{ id: 1, dataName: "发动机转速", buildStr: "ID: engine_rpm | 类型: 实时数据 | 单位: rpm" },{ id: 2, dataName: "发动机负荷", buildStr: "ID: engine_load | 类型: 实时数据 | 单位: %" },{ id: 3, dataName: "冷却液温度", buildStr: "ID: coolant_temp | 类型: 实时数据 | 单位: °C" },{ id: 4, dataName: "机油压力", buildStr: "ID: oil_pressure | 类型: 实时数据 | 单位: bar" },{ id: 5, dataName: "累计燃油消耗", buildStr: "ID: total_fuel | 类型: 累计数据 | 单位: L" },{ id: 6, dataName: "累计运行时间", buildStr: "ID: total_runtime | 类型: 累计数据 | 单位: h" },
])
右侧的三个目标分组:
const realtimeStatus = ref<AvailableDataSource[]>([]);
const cumulativeData = ref<AvailableDataSource[]>([]);
const performanceMetrics = ref<AvailableDataSource[]>([]);
2. 拖拽逻辑
使用 vue-draggable-plus
提供的 <VueDraggable>
组件:
<VueDraggable v-model="availableDataSource" :animation="150":group="{ name: 'dataset', pull: 'clone', put: false }":sort="false":clone="cloneHandler"><div v-for="item in availableDataSource" :key="item.id"class="data-item" :class="{ 'disabled': !isDraggable(item) }"><p class="label">{{ item.dataName }}</p><p class="desc">{{ item.buildStr }}</p><div class="check-box" v-if="!isDraggable(item)"><CheckOutlined class="icon" /></div></div>
</VueDraggable>
关键参数说明
-
group
: 设置拖拽分组,多个