vue 实现拖拽甘特图
实现拖拽甘特图的核心思路
Vue 实现拖拽甘特图需要结合第三方库或自定义逻辑,核心功能包括任务条渲染、时间轴刻度、拖拽交互、数据绑定等。以下是具体实现方法:
使用第三方库(推荐)
vue-ganttastic
专为 Vue 设计的轻量级甘特图库,支持拖拽、缩放和动态数据绑定:
npm install vue-ganttastic
示例代码:
<template>
<GanttChart :tasks="tasks" @task-updated="handleTaskUpdate" />
</template>
<script>
import { GanttChart } from 'vue-ganttastic';
export default {
components: { GanttChart },
data() {
return {
tasks: [
{ id: 1, name: 'Task 1', start: '2023-01-01', end: '2023-01-05' },
{ id: 2, name: 'Task 2', start: '2023-01-06', end: '2023-01-10' }
]
};
},
methods: {
handleTaskUpdate(updatedTask) {
// 更新数据逻辑
}
}
};
</script>
dhtmlx-gantt
功能强大的商业库,支持复杂场景:

npm install dhtmlx-gantt
配置示例:
<template>
<div ref="ganttContainer"></div>
</template>
<script>
import { gantt } from 'dhtmlx-gantt';
export default {
mounted() {
gantt.init(this.$refs.ganttContainer);
gantt.parse(this.tasks);
gantt.config.drag_move = true;
},
data() {
return { tasks: [...] };
}
};
</script>
自定义实现方案
基础结构
通过 HTML + CSS 构建甘特图框架:
<template>
<div class="gantt-container">
<div class="timeline">
<div v-for="day in days" :key="day">{{ day }}</div>
</div>
<div class="tasks">
<div
v-for="task in tasks"
:key="task.id"
class="task-bar"
:style="calcTaskStyle(task)"
draggable
@dragstart="dragStart(task)"
@dragend="dragEnd"
></div>
</div>
</div>
</template>
拖拽逻辑实现
处理任务条的拖拽和位置计算:

methods: {
calcTaskStyle(task) {
const startPos = this.dateToPixel(task.start);
const width = this.dateToPixel(task.end) - startPos;
return { left: `${startPos}px`, width: `${width}px` };
},
dragStart(task) {
this.draggedTask = task;
event.dataTransfer.setData('text/plain', task.id);
},
handleDrop(event) {
const newStart = this.pixelToDate(event.clientX);
this.updateTask(this.draggedTask.id, { start: newStart });
}
}
时间轴计算
日期与像素位置的转换方法:
dateToPixel(date) {
const dayWidth = 30; // 每个日期单位的像素值
const startDate = new Date('2023-01-01');
const diffDays = Math.floor((new Date(date) - startDate) / (1000 * 60 * 60 * 24));
return diffDays * dayWidth;
}
关键优化点
性能优化
对于大量任务数据,使用虚拟滚动技术:
<VirtualScroll :items="tasks" :itemHeight="30">
<template v-slot="{ item }">
<GanttTask :task="item" />
</template>
</VirtualScroll>
交互增强
添加拖拽手柄和限制条件:
.task-bar {
position: relative;
}
.task-handle {
width: 8px;
background: #666;
cursor: ew-resize;
}
注意事项
- 时区处理:所有日期建议使用 ISO 格式(如
2023-01-01T00:00:00Z) - 数据持久化:拖拽后需触发 API 更新后端数据
- 移动端适配:触摸事件需额外实现
touchstart/touchmove
可根据项目复杂度选择第三方库或自定义方案,复杂项目推荐使用 dhtmlx-gantt,轻量级需求可选择 vue-ganttastic 或自定义实现。






