vue实现拖拽甘特图
Vue 实现拖拽甘特图的方法
使用现成组件库(推荐快速实现)
推荐使用 vue-gantt-elastic 或 dhtmlx-gantt 这类专门为 Vue 封装的甘特图库,它们内置拖拽功能。
安装 vue-gantt-elastic:
npm install vue-gantt-elastic
基础实现代码:
<template>
<gantt-elastic
:tasks="tasks"
:options="options"
@task-dragged="handleTaskDrag"
/>
</template>
<script>
import GanttElastic from "vue-gantt-elastic";
export default {
components: { GanttElastic },
data() {
return {
tasks: [
{ id: 1, start: "2024-01-01", end: "2024-01-05", title: "任务1" }
],
options: {
draggable: { enabled: true }
}
};
},
methods: {
handleTaskDrag(payload) {
console.log("拖拽更新:", payload);
}
}
};
</script>
自定义实现拖拽甘特图
如果需要完全自定义,可以结合以下技术栈:
- 使用
<div>和 CSS Grid/Flex 布局绘制甘特图 - 通过 Vue 的
v-for渲染任务条 - 利用 HTML5 原生拖拽 API 或第三方库如
interact.js
核心拖拽逻辑示例:
<template>
<div class="gantt-container">
<div
v-for="task in tasks"
:key="task.id"
class="task-bar"
draggable="true"
@dragstart="dragStart(task)"
@dragend="dragEnd"
@dragover.prevent
@drop="dropTask(task)"
></div>
</div>
</template>
<script>
export default {
data() {
return {
tasks: [...],
draggedTask: null
}
},
methods: {
dragStart(task) {
this.draggedTask = task;
},
dropTask(targetTask) {
// 更新任务位置逻辑
const newTasks = this.tasks.map(t =>
t.id === this.draggedTask.id
? { ...t, start: targetTask.start }
: t
);
this.tasks = newTasks;
}
}
}
</script>
<style>
.gantt-container {
display: grid;
grid-template-columns: repeat(30, 1fr); /* 30天 */
}
.task-bar {
background: #4CAF50;
height: 20px;
grid-column: span 3; /* 默认3天 */
}
</style>
关键功能实现要点
时间轴处理建议使用 moment.js 或 date-fns 计算日期跨度:
import { format, addDays } from 'date-fns';
// 计算任务天数
const days = differenceInCalendarDays(
new Date(task.end),
new Date(task.start)
);
拖拽边界检测需要限制任务不能超出甘特图范围:
dropTask(e) {
const newStart = /* 计算新位置 */;
if (newStart < this.minDate || newStart > this.maxDate) return;
// 更新数据
}
性能优化建议
对于大数据量场景:

- 使用虚拟滚动(如
vue-virtual-scroller) - 节流拖拽事件处理
- 使用 Vue 的
v-memo优化重复渲染
<template>
<div v-for="task in tasks" v-memo="[task.id, task.start]">
<!-- 任务条内容 -->
</div>
</template>





