Skip to content

虚拟滚动

当任务数量较多时(超过 100 个),虚拟滚动可以显著提升渲染性能。

工作原理

虚拟滚动只渲染当前可视区域内的任务,而不是渲染所有任务。这使得 GanttFlow 能够轻松处理数千条任务数据。

┌─────────────────────────────┐
│  Header (固定)               │
├────────────┬────────────────┤
│            │  ████████████  │  ← 可视区域
│  Task List │  ████████████  │    只渲染可见任务
│            │  ████████████  │
│            │  ████████████  │
├────────────┼────────────────┤
│            │  ████████████  │  ← 缓冲区
│            │  (虚拟空白)     │    保持滚动条正确
│            │  (虚拟空白)     │
└────────────┴────────────────┘

启用虚拟滚动

tsx
<EnhancedGanttChart
  tasks={largeTaskList}  // 假设有 1000+ 任务
  virtualScrolling={true}
  visibleTaskCount={50}  // 可见任务数量
  bufferSize={10}        // 缓冲区大小
/>

配置参数

参数类型默认值说明
virtualScrollingbooleanfalse是否启用虚拟滚动
visibleTaskCountnumber50可见区域渲染的任务数
bufferSizenumber10上下缓冲区渲染的任务数

性能优化建议

合理设置可见数量

根据屏幕大小设置可见任务数:

tsx
// 小屏幕设备
<EnhancedGanttChart
  virtualScrolling={true}
  visibleTaskCount={30}
/>

// 大屏幕设备
<EnhancedGanttChart
  virtualScrolling={true}
  visibleTaskCount={80}
/>

// 响应式设置
function useVisibleTaskCount() {
  const { height } = useWindowSize()
  
  if (height < 600) return 25
  if (height < 900) return 50
  return 80
}

配合自适应密度

可以结合自适应密度功能获得最佳体验:

tsx
<EnhancedGanttChart
  virtualScrolling={true}
  adaptiveDensity={true}       // 自动调整布局密度
  densityThreshold={100}        // 超过此数量自动启用自适应
/>

使用懒加载

对于超大数据集,可以配合懒加载:

tsx
const loadMoreTasks = async () => {
  const newTasks = await fetchTasks(currentPage + 1)
  setTasks([...tasks, ...newTasks])
}

<EnhancedGanttChart
  tasks={tasks}
  virtualScrolling={true}
  onScrollBottom={loadMoreTasks}
/>

性能对比

任务数量无虚拟滚动启用虚拟滚动
50✅ 流畅✅ 流畅
200⚠️ 卡顿✅ 流畅
500🐢 明显卡顿✅ 流畅
1000❌ 无法使用✅ 流畅
5000❌ 崩溃✅ 流畅

调试模式

开发时可以开启性能日志:

tsx
<EnhancedGanttChart
  tasks={tasks}
  virtualScrolling={true}
  debugMode={true}  // 显示性能日志
/>

调试模式会显示:

  • 当前渲染的任务数量
  • 滚动位置
  • FPS(帧率)
  • 渲染时间

常见问题

Q: 启用虚拟滚动后,滚动不流畅?

A: 检查以下几点:

  1. 减少可见任务数
tsx
<EnhancedGanttChart visibleTaskCount={30} />
  1. 禁用动画
tsx
<EnhancedGanttChart enableAnimations={false} />
  1. 检查设备性能:虚拟滚动需要设备有足够的内存和处理能力

Q: 任务高度不一致时显示异常?

A: 确保所有任务有固定的行高,或设置 variableRowHeight={true}

tsx
<EnhancedGanttChart
  virtualScrolling={true}
  rowHeight={44}  // 固定行高
/>

Q: 拖拽时虚拟滚动行为异常?

A: 拖拽过程中可以临时禁用虚拟滚动:

tsx
const [isDragging, setIsDragging] = useState(false)

<EnhancedGanttChart
  tasks={tasks}
  virtualScrolling={!isDragging}
  onTaskDragStart={() => setIsDragging(true)}
  onTaskDragEnd={() => setIsDragging(false)}
/>

最佳实践

自动启用

tsx
// 当任务数量超过阈值时自动启用虚拟滚动
const shouldEnableVirtualScroll = tasks.length > 100

<EnhancedGanttChart
  tasks={tasks}
  virtualScrolling={shouldEnableVirtualScroll}
  visibleTaskCount={shouldEnableVirtualScroll ? 50 : undefined}
/>

任务数据优化

tsx
// ✅ 推荐:保持任务数据简洁
const tasks = largeTaskList.map(task => ({
  id: task.id,
  name: task.name,
  start: task.start,
  end: task.end,
  progress: task.progress
}))

// ❌ 不推荐:保留大量无关数据
const tasks = largeTaskList  // 可能包含 description, notes, assignees 等大量数据

合理使用缓冲区

tsx
// 缓冲区太小会导致滚动时出现空白
<EnhancedGanttChart bufferSize={5} />  // 太小

// 缓冲区太大会影响性能
<EnhancedGanttChart bufferSize={50} /> // 太大

// 推荐:缓冲区为可见数量的 20%
<EnhancedGanttChart
  visibleTaskCount={50}
  bufferSize={10}
/>

实现原理

虚拟滚动的核心原理:

1. 计算可视区域
   - 根据滚动位置和容器高度
   - 确定可见的任务索引范围

2. 计算渲染范围
   - 可见范围 + 缓冲区
   - 确定需要渲染的任务

3. 渲染任务
   - 只渲染计算出的任务
   - 使用 transform 定位

4. 保持滚动条正确
   - 计算总高度(所有任务高度之和)
   - 创建虚拟容器维持滚动条比例

下一步

基于 MIT 许可证发布