自定义渲染
先用主题令牌、尺寸和 Resolver 调整外观;只有结构或业务内容需要变化时,再使用 Vue Slot、React Render Prop 或 Flutter Builder。这样能保留虚拟化、拖放、无障碍和边缘跳转协议。
跨端扩展面
| 区域 | Vue | React | Flutter |
|---|---|---|---|
| 任务表 | task-* 表头、task、owner、progress Slots | renderTaskHeader、renderTask、renderOwner、renderProgress | rowHeaderBuilder |
| 任务条 | bar、bar-pattern、bar-effect | renderBar、taskPattern | taskBarBuilder |
| 依赖线 | dependency Slot 与 Path / Style / Effect Resolver | renderDependency | Alpha 1 使用主题色与内置几何 |
| 视口外入口 | edge-indicator | renderEdgeIndicator | edgeIndicatorBuilder |
| 空状态 | empty | renderEmpty | 由宿主在空任务时组合 |
| 入场过渡 | viewportEnterEffect 与 CSS | entryEffect | entryTransitionBuilder |
Vue Slots
vue
<YgGantt :tasks="tasks">
<template #bar="{ task, progress }">
<TaskBarContent :task="task" :progress="progress" />
</template>
<template #edge-indicator="{ side, task, jump }">
<button type="button" :aria-label="`定位到 ${task.title}`" @click="jump">
{{ side === 'left' ? '‹' : '›' }}
</button>
</template>
</YgGantt>Vue 还提供 toolbar-extra、三列表头、完整依赖 SVG、纹理层和效果层。每个 Slot 的精确作用域见 Vue API。
React Render Props
tsx
<YgGantt
tasks={tasks}
renderBar={({ task, progress }) => (
<TaskBarContent task={task} progress={progress} />
)}
renderEdgeIndicator={({ side, task, jump }) => (
<button aria-label={`定位到 ${task.title}`} onClick={jump}>
{side === 'left' ? '‹' : '›'}
</button>
)}
/>Render Prop 应返回轻量节点。不要为每个可见任务重复创建大型图表、滤镜或持续布局动画。
Flutter Builders
dart
YotsubaGantt(
tasks: tasks,
taskBarBuilder: (context, details) {
return TaskBarContent(task: details.task, selected: details.selected);
},
edgeIndicatorBuilder: (context, details) {
return IconButton(
tooltip: '定位到 ${details.task.title}',
onPressed: details.jump,
icon: Icon(details.side == YgEdgeSide.left
? Icons.chevron_left
: Icons.chevron_right),
);
},
)性能边界
- 自定义渲染只会为虚拟窗口内的任务执行,但单个节点成本仍由宿主承担。
- 图片纹理应复用缓存资源;避免为每条任务解码独立大图。
- 进入视口的过渡只使用
opacity和transform,持续效果应限制在选中或少量任务。 - 边缘入口必须保留
jump(),依赖线编辑必须保留edit(),否则会丢失内置交互。
