React Gantt 概览
React Gantt 可在 Commercial, Enterprise and Ultimate 许可 下获得。 如果您正在使用免费 Community 版(v10+)、或较早版本的 GPL 版(v9.x 及更早),或 Gantt 的 Individual 版,请参考 React 的 如何入门 文章。
概览
DHTMLX Gantt 是一个 纯 JavaScript 组件,可以在任何浏览器环境中工作。Gantt 的 Commercial 及更高版本包括一个 React Gantt 组件,它对 DHTMLX Gantt 进行了封装,允许你在 React 中原生地使用它。
这个封装器让你在 React 应用中使用熟悉的 props/state 模型来创建一个功能完备的 Gantt 图。在内部,它管理一个标准的 DHTMLX Gantt 实例,将你的 React props(如任务、配置等)转换成相应的 Gantt 初始化和数据结构。
关键特性
- 声明式数据处理:把任务、链接、资源等作为 props 传递的数组处理。
- 配置性强:将 React props 映射到底层的 gantt.config、gantt.templates、gantt.plugins 等。
- 访问完整的 Gantt API:通过 ref 调用诸如 getTask、updateTask、或 addTaskLayer 等方法。
- 易于定制:使用 React 组件实现模板、轻量表单或内联编辑器等。
如果你是 DHTMLX Gantt 的新用户,请参阅 DHTMLX Gantt 文档 以了解诸如 Work Time Calculation、Auto Scheduling、Resource Management 等特性概览。
如果你使用 AI 代码助手,DHTMLX React Gantt agent skill 可以帮助它遵循正确的集成模式并避免常见错误。要获取实时 API 参考,请连接 DHTMLX MCP 服务器。
安装与 NPM 访问
关于 Evaluation 和 Professional 构建的最新安装说明(包括 npm registry 配置和离线示例),请参阅 安装指南。
安装包后,你可以在 React 代码中按如下方式导入封装器:
// Evaluation 构建(公共 npm)
import ReactGantt from '@dhtmlx/trial-react-gantt';
import '@dhtmlx/trial-react-gantt/dist/react-gantt.css';
// Professional 构建(私有 npm)
import ReactGantt from '@dhx/react-gantt';
import '@dhx/react-gantt/dist/react-gantt.css';
版本要求
- React v18.0.0 或更高
基本用法
下方是一段最小的代码片段,展示如何导入并渲染 Gantt 图:
import { useState } from 'react';
import ReactGantt from '@dhx/react-gantt';
import '@dhx/react-gantt/dist/react-gantt.css';
import { demoData } from './DemoData'
export default function BasicGantt() {
const [theme, setTheme] = useState("terrace");
const [tasks, setTasks] = useState(demoData.tasks);
const [links, setLinks] = useState(demoData.links);
return (
<div style={ { height: '500px' }}>
<ReactGantt
tasks={tasks}
links={links}
theme={theme}
/>
</div>
);
}
请注意,上面这段代码片段展示的是商业版 Gantt 的用法。若要使用试用代码源,请按如下方式包含包:
import ReactGantt from '@dhtmlx/trial-react-gantt';
import '@dhtmlx/trial-react-gantt/dist/react-gantt.css';
其中 demoData 的格式如下 format:
export const demoData = {
tasks: [
{ id: 1, text: "Product Launch", type: "project", open: true, parent: 0},
{ id: 2, text: "Planning Phase", type: "project", open: true, parent: 1},
{ id: 3, text: "Requirement Gathering", type: "task", progress: 0.2,
start_date: "01-06-2025", duration: 3, parent: 2},
{ id: 4, text: "Technical Feasibility", type: "task", progress: 0.4,
start_date: "04-06-2025", duration: 2, parent: 2},
{ id: 5, text: "Implementation Phase", type: "project", progress: 0.1,
open: true, start_date: "08-06-2025", duration: 10, parent: 1},
{ id: 6, text: "Prototype Development", type: "task", progress: 0.0,
start_date: "08-06-2025", duration: 4, parent: 5},
{ id: 7, text: "Feature Testing", type: "task", progress: 0.0,
start_date: "12-06-2025", duration: 4, parent: 5},
{ id: 8, text: "Go-Live Milestone", type: "milestone", progress: 0,
start_date: "18-06-2025", duration: 0, parent: 1}
],
links: [
{ id: 1, source: 3, target: 4, type: "0" },
{ id: 2, source: 4, target: 5, type: "0" },
{ id: 3, source: 6, target: 7, type: "0" },
{ id: 4, source: 7, target: 8, type: "0" }
]
};
export {demoData};
绑定数据
React Gantt 封装器提供了加载和保存数据的灵活方法。从概念上讲,有两种主要的更改绑定模型:
- React(或一个状态管理器)作为真实数据源
- Gantt 作为真实数据源
任一方法都是有效的,但你应该选择一种并始终如一地遵循,以避免出现意外行为。
本节提供两种绑定模型的高级概览。若需要更详细的指南(包含完整示例),请参阅 Basics。
以 React(或状态管理器)作为真实数据源
在这种模式下,ReactGantt 通过 props 接收所有任务/链接数据(来自 useState、Redux、Zustand 等)。每当用户在图表中修改任务或链接时,Gantt 会调用 data.save 回调。在该回调中,你更新应用的状态。当状态变化时,React 会重新渲染 ReactGantt,并让 Gantt 实例与最新数据同步。
import { useMemo, useState } from 'react';
import ReactGantt, { type Task, type Link } from '@dhtmlx/trial-react-gantt';
import '@dhtmlx/trial-react-gantt/dist/react-gantt.css';
export function MyGanttApp({ initialTasks, initialLinks }: {
initialTasks: Task[];
initialLinks: Link[];
}) {
const [tasks, setTasks] = useState<Task[]>(initialTasks);
const [links, setLinks] = useState<Link[]>(initialLinks);
const data = useMemo(
() => ({
save: (entity: string, action: string, item: any, id: string | number) => {
if (entity === 'task') {
setTasks((prev) => {
if (action === 'create') return [...prev, item as Task];
if (action === 'update') return prev.map((task) =>
task.id === id ? (item as Task) : task
);
if (action === 'delete') return prev.filter((task) => task.id !== id);
return prev;
});
}
if (entity === 'link') {
setLinks((prev) => {
if (action === 'create') return [...prev, item as Link];
if (action === 'update') return prev.map((link) =>
link.id === id ? (item as Link) : link
);
if (action === 'delete') return prev.filter((link) => link.id !== id);
return prev;
});
}
},
})),
[]
);
return (
<ReactGantt
tasks={tasks}
links={links}
data={data}
/>
);
}
这种方式使你的 React(或全局)状态成为唯一的数据来源。它与 Redux Toolkit、Zustand、MobX、Jotai、XState 或 Valtio 等状态管理工具天然协作——你只需用你的商店钩子/选择器替换 useState,并将更新逻辑移入到商店中。
更多示例(包括与特定管理器的集成)请参阅 React 状态作为真相来源。
将 Gantt 作为真实数据源
在这种方法中,Gantt 本身 持有数据的权威副本。你仍然通过 props 或 URL 初始化或加载任务和链接,但一旦图表运行,Gantt 会在内部处理变更并将更新转发到你的后端或自定义处理程序,而不是在每次编辑时通过 React 状态进行。
import ReactGantt from '@dhtmlx/trial-react-gantt';
import '@dhtmlx/trial-react-gantt/dist/react-gantt.css';
export function GanttTransportExample() {
return (
<ReactGantt
data={{
load: '/api/gantt/data', // Gantt 通过该端点加载任务/链接
save: '/api/gantt/data', // Gantt 将变更发送回这里
}}
/>
);
}
在这种模式下:
- 本地 Gantt 实例保留当前数据的权威拷贝
- React 不会在每次任务/链接变动时重新渲染
- 像自动排程这样的批量操作成本更低,因为它们不会触发重复的 React 更新
如果你仍然在 React 状态中保留某些任务/链接的表示,请小心不要用过时的数据覆盖 Gantt 的内部状态。
更多细节请参阅 Gantt 作为真相来源。
配置与 Props
React 封装器接收 config prop(映射到 gantt.config)以及 templates prop(映射到 gantt.templates)。
<ReactGantt
tasks={tasks}
links={links}
config= {{
scales: [
{ unit: "year", step: 1, format: "%Y" },
{ unit: "month", step: 1, format: "%F, %Y" },
{ unit: "day", step: 1, format: "%d %M" },
],
columns: [
{ name: "text", tree: true, width: "*", resize: true },
{ name: "start_date", align: "center", resize: true },
{ name: "duration", align: "center", resize: true },
{
name: "custom",
align: "center",
template: (task) => <AlertButton task={task} onClick={handleButtonClick} />,
resize: true,
},
{ name: "add", width: 44 },
],
}}
templates= {{
task_text: (start, end, task) => `#${task.id}: ${task.text}`,
task_class: (start, end, task) => {
return task.priority === 'high' ? 'highlight-task' : '';
},
}}
/>
在模板中使用 React 组件
在属性中指定模板时,你可以从模板函数返回 React 元素:
function PriorityBadge({ priority }) {
return <span style={{color: 'red' }}>{priority}</span>;
}
<ReactGantt
templates={{
task_text: (start, end, task) => {
return <PriorityBadge priority={task.priority} />;
}
}}
/>
内部而言,DHTMLX Gantt 以非 React 的方式操作 DOM。当你从模板返回 React 组件时,它们通过门户(portals)嵌入到 Gantt 的 HTML 中。请记住,对于大型数据集,呈现大量的复杂 React 组件可能影响性能。
你可以通过模板覆盖许多方面: