刚转Vue3,项目里要加甘特图,不知道从哪入手?好用的组件和原生实现思路都帮你理清楚
刚把旧项目从Vue2升级到Vue3,或者直接上手Vue3做新项目,很多做项目管理、生产排期、运维调度、课程规划类功能的开发者都会卡在甘特图这个节点——毕竟这东西说简单不简单,拖拽、缩放、层级关联、联动这些交互一个都不能少,纯手写太费时间,随便找个组件库又怕兼容性差、功能不全、不好二次开发,今天就结合我最近半年做3个排期项目踩过的坑、攒下的经验,从核心需求拆解、主流Vue3甘特图组件对比、原生简易版实现三步,把这个事说透。
第一步:先搞懂你的项目“真的需要”什么样的甘特图?
很多时候开发者上来就搜“Vue3最好用的甘特图组件”,其实这是个伪命题——没有最好的,只有最适合的,我见过太多人一开始图省事选了功能最全的,结果上线后性能爆炸,手机端完全卡成PPT,或者业务只需要甘特图展示,不需要复杂交互,却付了付费组件的冤枉钱,所以咱们先花2分钟,把核心需求列成清单打勾,后面选组件或者写代码就能精准踩点。
我整理了一份高频甘特图需求对照表,你可以对着填:
- 展示维度:是单维度的“时间-任务”,还是要加资源维度的“资源-时间-任务”(就是资源甘特图,生产排期、共享会议室排期常用)?
- 时间范围跨度:是分钟级(比如直播排期、运维巡检排程)、小时/天级(普通项目管理)、周/月/季级(长期项目规划),还是需要支持跨年份切换?
- 核心交互:要不要拖拽调整任务的前后时间?要不要拖拽缩放任务的时长?要不要拖拽调整任务的层级(父任务子任务折叠展开)?要不要任务之间的依赖连线(FS、SS、FF、SF这四种工程上的依赖关系要全吗?)?要不要任务的拖拽排序?
- 数据交互:要不要实时更新数据(WebSocket同步多端操作)?要不要导出成PDF、Excel、图片?要不要支持任务详情的点击弹窗?
- 适配场景:要不要适配移动端?要不要暗黑模式?要不要支持多国语言?
- 预算与开源协议:是完全开源免费就行?还是可以接受基础版免费、高级版付费?开源协议有没有商业限制(MIT协议最宽松,LGPL其次,GPL如果是商业项目要谨慎)?
举个我自己的例子,上个月做了个企业内部的共享工位排期小程序Web端,展示维度是“工位-日期时间段-员工姓名”,时间范围是分钟级到周级切换,核心交互只有工位时间段的拖拽新建、拖拽调整、拖拽删除、时间段冲突检测,不需要依赖连线、层级折叠,预算为0(公司没给开源以外的费用),还要适配手机端竖屏,根据这个清单,我直接排除了DHTMLX Gantt这种功能全但移动端适配差、高级功能付费的,也排除了手写代码量太大的,最后选了一个轻量的、MIT协议的、专门做资源甘特图的Vue3组件。
第二步:主流Vue3甘特图组件大对比,总有一款适合你
现在市面上能找到的Vue3甘特图组件不少,但真正稳定、更新频繁、文档全的没几个,我从GitHub星星数、更新频率、功能覆盖、开源协议、移动端适配、二次开发难度这六个维度,挑了5款用得最多的来对比,给你做参考。
第一款:DHTMLX Gantt for Vue3
如果你的项目是大型、复杂的工程类/项目管理类Web端项目,预算充足,对依赖连线、资源负载、关键路径计算这些专业功能要求极高,那DHTMLX Gantt绝对是首选。 它的优势特别明显:首先是功能全到离谱——所有你能想到的甘特图功能它都有,甚至还有预算管理、成本计算、甘特图对比这种小众但有用的功能;其次是性能强,哪怕加载10000条任务数据也不会太卡;第三是二次开发文档极其详细,每个API、每个事件、每个样式类都有说明和示例,连基础的CSS变量都开放了,改颜色改字体改布局非常方便;第四是有专业的技术支持,付费后遇到问题基本24小时内就能得到回复。 当然它的劣势也很突出:一是核心高级功能(比如资源甘特图、关键路径、PDF导出带水印去除)完全付费,免费版只能用基础的拖拽、缩放、简单依赖,而且导出的图片/PDF都带大大的DHTMLX水印;二是移动端适配一般,竖屏的时候任务栏和时间轴都特别小,点击操作很困难;三是库体积有点大,压缩后大概有200KB左右,对首屏加载速度要求极高的项目要慎重。
第二款:FullCalendar Gantt Plugin
别惊讶,FullCalendar不只是做日历的,它还有专门的甘特图插件,而且完全兼容Vue3。 这款适合的场景是中大型的、时间范围跨度较大的、不需要太复杂任务层级和依赖的项目管理类应用,比如公司的季度任务规划、学校的学期课程安排。 它的优势在于:一是完全开源免费,MIT协议,没有任何商业限制;二是库体积小,只引入甘特图插件的话,压缩后大概只有50KB左右;三是继承了FullCalendar强大的时间轴适配能力,从分钟级到世纪级都能完美切换,手机端适配做得也不错,竖屏横屏都能看;四是和FullCalendar的其他插件兼容性好,如果你的项目里本来就用了FullCalendar做日历,直接加甘特图插件就行,不用再重新引入一套新的库。 它的劣势也很致命:一是任务层级只有两层,父任务下面只能挂子任务,不能再挂孙任务;二是依赖连线只有FS一种,也就是“前一个任务结束后一个任务才能开始”,其他三种专业依赖完全没有;三是拖拽缩放任务的时长不能精确到分钟,只能到小时/天,生产排期、直播排期这种分钟级的项目用不了;四是没有专业的技术支持,只能靠GitHub的Issue和社区论坛求助,解决问题的速度很慢。
第三款:Vue-Gantt-Chart
这是一款专门为Vue3打造的轻量级甘特图组件,GitHub星星数不算多(大概3000左右),但更新频率很高,最近一次更新是2024年5月。 这款适合的场景是中小型的、时间范围在小时/天到月级的、需要简单拖拽缩放和层级折叠的项目管理类应用,比如个人的待办事项、小团队的短期项目排期。 它的优势在于:一是完全开源免费,MIT协议,没有商业限制;二是库体积特别小,压缩后大概只有20KB左右;三是代码结构简单清晰,二次开发难度极低,哪怕你是刚学Vue3的新手,看看源码就能改;四是支持任务的拖拽排序、拖拽调整前后时间、拖拽缩放时长、层级折叠展开,基本能满足中小型项目的需求;五是支持暗黑模式,这个细节做得很好。 它的劣势在于:一是没有任务之间的依赖连线,完全不能做工程类的项目;二是数据交互功能比较弱,没有内置的导出功能,也没有WebSocket同步的示例;三是文档比较简单,只有基础的API说明和一个简单的示例,很多进阶功能需要自己摸索;四是手机端适配一般,竖屏的时候需要左右滑动很多次才能看完整个时间轴。
第四款:Bryntum Gantt for Vue3
如果你的项目是大型的、专业的工程类/生产排期类应用,预算比DHTMLX Gantt更充足,对性能和功能的要求都到了极致,那Bryntum Gantt可以考虑一下。 它的优势比DHTMLX Gantt还要夸张:首先是性能更强,官方测试加载100000条任务数据都不会卡,而且支持虚拟滚动,不管加载多少数据,只渲染可视区域内的部分;其次是功能最全,除了DHTMLX Gantt有的所有功能,它还有甘特图与日历、资源调度、图表的联动,还有AI辅助排程的功能;第三是二次开发的自由度最高,它完全是用原生TypeScript写的,没有依赖任何其他的库,所有的组件都是可定制的,甚至可以自己重写整个渲染引擎;第四是移动端适配做得最好,竖屏横屏都能完美操作,还支持触摸手势;第五是有顶级的技术支持,付费后可以直接和开发团队沟通。 它的劣势只有一个,但也是很多人望而却步的:价格太贵,商业授权的起步价是每年2999美元,而且每个项目都要单独授权,对中小企业和个人开发者来说完全负担不起。
第五款:VChart Gantt
这是字节跳动火山引擎DataV团队推出的一款可视化图表库,里面包含了甘特图组件,完全兼容Vue3。 这款适合的场景是对数据可视化要求较高、不需要太复杂交互的甘特图展示类应用,比如项目汇报PPT里的甘特图截图、公司官网的项目进度展示。 它的优势在于:一是完全开源免费,Apache-2.0协议,没有商业限制;二是库体积适中,只引入甘特图组件的话,压缩后大概有80KB左右;三是数据可视化能力极强,可以给任务设置渐变颜色、阴影、图标,还可以和VChart的其他图表(比如柱状图、折线图、饼图)联动,展示项目的进度百分比、资源负载率等数据;四是文档极其详细,每个API、每个配置项都有说明和交互式示例,哪怕你是可视化小白,也能很快上手;五是有火山引擎DataV团队的技术支持,虽然是免费的,但GitHub的Issue回复速度很快。 它的劣势在于:一是交互功能比较弱,只有简单的点击任务高亮、层级折叠展开,没有拖拽缩放、拖拽排序、依赖连线这些核心交互;二是资源甘特图的支持不够完善,只能做简单的资源-任务对应,不能做资源负载率的展示。
第三步:原生Vue3简易甘特图实现思路,实在找不到合适的就自己写
如果上面的5款组件都不符合你的需求,或者你预算为0但又需要一些特定的功能(比如我上个月做的共享工位排期的时间段冲突检测),那自己手写一个简易版的Vue3甘特图其实也不难——核心就是用Vue3的响应式数据和CSS的Flexbox布局,把任务条放在时间轴上,再加上一些简单的鼠标/触摸事件监听就行。
接下来我就给你讲一下原生实现的核心思路,代码量大概在500行左右,你可以直接拿去改。
1 核心数据结构设计
不管是展示还是交互,数据结构都是基础,我设计的核心数据结构是这样的:
- 甘特图配置项:包括时间范围的起始时间和结束时间、时间轴的刻度(分钟、小时、天、周、月)、任务栏的宽度、每个时间刻度的宽度。
- 任务数据:每个任务要有唯一的id、任务名称、任务的起始时间和结束时间、任务的父任务id(如果是子任务的话)、任务的执行人/资源(如果是资源甘特图的话)。
2 核心布局实现
布局我用的是Vue3的插槽和CSS的Flexbox,分为三个部分:
- 任务列表区:放在左边,固定宽度,展示任务的名称、执行人/资源等信息,每个任务占一行,高度可以自己设置。
- 时间轴区:放在任务列表区的上面,宽度自适应,展示时间刻度,每个时间刻度占固定宽度,和任务条的位置对应。
- 任务条区:放在右边,宽度自适应,和时间轴区的宽度一致,高度和任务列表区的高度一致,里面放所有的任务条,任务条的位置通过计算任务的起始时间和甘特图配置项的起始时间的差值来确定(left = 差值 / 每个时间刻度的时间跨度 每个时间刻度的宽度),任务条的宽度通过计算任务的结束时间和起始时间的差值来确定(width = 差值 / 每个时间刻度的时间跨度 每个时间刻度的宽度)。
3 核心交互实现
核心交互我用的是Vue3的@mousedown、@mousemove、@mouseup、@mouseleave事件,还有@touchstart、@touchmove、@touchend事件,这样既能适配PC端,又能适配移动端。
我举三个最常用的交互的实现思路:
- 拖拽调整任务的前后时间:在任务条的左边加一个小手柄,当用户鼠标按下或者触摸这个小手柄时,记录下当前的鼠标/触摸位置、任务的起始时间和结束时间,当用户鼠标移动或者触摸移动时,计算出鼠标/触摸位置的变化量,然后根据变化量和每个时间刻度的时间跨度来更新任务的起始时间,任务条的left和width也会随之自动更新(因为我们用的是Vue3的响应式数据),当用户鼠标松开或者触摸结束时,保存更新后的任务数据。
- 拖拽缩放任务的时长:在任务条的右边加一个小手柄,实现思路和拖拽调整前后时间差不多,只是更新的是任务的结束时间,任务条的width会随之自动更新。
- 时间段冲突检测:这是我上个月做共享工位排期时必须要加的功能,实现思路很简单:当用户拖拽新建或者拖拽调整任务条时,遍历所有同一资源下的任务,判断当前任务的起始时间和结束时间是否和其他任务的起始时间和结束时间有重叠,如果有重叠,就给当前任务条加一个红色的边框或者背景色,提示用户时间段冲突。
4 性能优化建议
如果你的任务数据比较多(超过1000条),那原生实现的甘特图可能会有点卡,这里我给你提几个性能优化建议:
- 使用虚拟滚动:不管是任务列表区还是任务条区,都只渲染可视区域内的部分,虚拟滚动的实现可以用Vue3官方推荐的
vue-virtual-scroller组件,也可以自己手写。 - 使用
v-once或者v-memo:如果任务的信息不会变化(比如任务名称、执行人/资源),就给任务列表区的内容加v-once,如果任务的信息只有在特定条件下才会变化(比如任务的起始时间和结束时间只有在拖拽时才会变化),就给任务条加v-memo,这样可以减少不必要的重新渲染。 - 防抖节流:在
@mousemove、@touchmove事件里加防抖或者节流,避免频繁更新响应式数据,影响性能。 - 使用CSS硬件加速:给任务条加
transform: translateZ(0)或者will-change: left, width,这样可以让浏览器用GPU来渲染任务条,提高性能。
到底是选组件还是自己写?
这是很多开发者都会纠结的问题,我的建议是:
- 如果你的项目时间紧、任务重、预算充足,而且对功能的要求比较高,那就直接选组件——DHTMLX Gantt或者Bryntum Gantt都可以。
- 如果你的项目时间紧、任务重、预算为0,而且对功能的要求不高,那就选开源免费的组件——FullCalendar Gantt Plugin或者Vue-Gantt-Chart都可以。
- 如果你的项目时间充裕、预算为0,而且对功能的要求比较特殊,或者你想学习一下甘特图的实现原理,那就自己手写。
不管是选组件还是自己写,最重要的是先搞懂你的项目“真的需要”什么样的甘特图,不要盲目追求功能全,适合自己的才是最好的。
好了,今天关于Vue3甘特图的内容就讲到这里,希望能帮到你,如果你还有什么问题,欢迎在评论区留言,我会一一回复的。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
code前端网


