ant-design-vue Timeline 时间轴组件完全指南:API、源码实现与实战示例
【免费下载链接】ant-design-vue🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜项目地址: https://gitcode.com/gh_mirrors/an/ant-design-vue
导读
Timeline(时间轴)是 ant-design-vue 中用于垂直展示时间流信息的数据展示组件,适合呈现按时间排列的事件序列(如服务排查记录、订单流转、项目里程碑)。本文以 components/timeline/index.zh-CN.md 为骨架,结合 Timeline.tsx、TimelineItem.tsx 等源码与 demo 目录下的真实示例,系统讲解 Timeline 的全部 API、四种布局模式(left / alternate / right / 标签模式)、幽灵节点、倒序排列、自定义时间轴点等核心能力,让你在 Vue 3 项目中能直接上手并理解其底层渲染逻辑。
一、组件定位与何时使用
Timeline 的核心价值在于用一根垂直轴线把按时间顺序排列的信息视觉串联起来。官方文档给出两条使用准则:
- 当有一系列信息需按时间排列时,可正序和倒序展示;
- 需要有一条时间轴进行视觉上的串联时使用。
典型业务场景包括:服务上线/故障处理时间线、订单状态流转记录、项目迭代日志、操作审计记录等。它支持从left、alternate(交替)、right三种整体布局中切换,并允许在每个节点上自定义颜色、图标、标签与位置。
最简单的用法如下(与 demo/basic.vue 一致):
<a-timeline> <a-timeline-item>创建服务现场 2015-09-01</a-timeline-item> <a-timeline-item>初步排除网络异常 2015-09-01</a-timeline-item> <a-timeline-item>技术测试异常 2015-09-01</a-timeline-item> <a-timeline-item>网络异常正在修复 2015-09-01</a-timeline-item> </a-timeline>渲染结果:每个节点由左侧圆点(head)、连接线(tail)与右侧内容区(content)组成,最后一个节点不再绘制连接线。
二、Timeline 组件 API 详解
Timeline 主组件参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| mode | 通过设置mode改变时间轴和内容的相对位置 | left|alternate|right | left |
| pending | 指定最后一个幽灵节点是否存在或内容 | boolean | string | slot | false |
| pendingDot | 当最后一个幽灵节点存在时,指定其时间图点 | string | slot | <LoadingOutlined /> |
| reverse | 节点排序 | boolean | false |
源码印证:在 Timeline.tsx 中,这些 props 被定义为:
export const timelineProps = () => ({ prefixCls: String, pending: PropTypes.any, // 幽灵节点内容,布尔值只控制显隐 pendingDot: PropTypes.any, // 幽灵节点的时间轴点 reverse: booleanType(), // 是否倒序 mode: PropTypes.oneOf(tuple('left', 'alternate', 'right', '')), });并通过initDefaultProps设置默认值:reverse: false、mode: ''(空字符串等价于默认的left布局)。组件名为ATimeline,注册时同时注册Timeline.Item子组件(见 index.tsx)。
Timeline.Item 节点参数
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| color | 指定圆圈颜色blue, red, green,或自定义的色值 | string | blue | - |
| dot | 自定义时间轴点 | string | slot | - | - |
| label | 设置标签 | string | slot | - | 3.0 |
| position | 自定义节点位置 | left|right | - | - |
源码印证:TimelineItem.tsx 中:
export const timelineItemProps = () => ({ prefixCls: String, color: String, dot: PropTypes.any, pending: booleanType(), position: PropTypes.oneOf(tuple('left', 'right', '')).def(''), label: PropTypes.any, });默认color: 'blue'。节点内部 DOM 结构依次为:item-label(仅 label 存在时渲染)、item-tail(连接线)、item-head(圆点/自定义点)、item-content(内容区),对应 TimelineItem.tsx 的渲染函数。
三、四种布局模式:mode 与 position 的配合
1. 左侧布局(默认,mode="left")
所有节点的时间轴点都在内容左侧,这是默认行为。Timeline的getPositionCls函数(Timeline.tsx)实现了位置类名的完整决策逻辑:
const getPositionCls = (ele, idx: number) => { const eleProps = ele.props || {}; if (props.mode === 'alternate') { if (eleProps.position === 'right') return `${prefixCls.value}-item-right`; if (eleProps.position === 'left') return `${prefixCls.value}-item-left`; return idx % 2 === 0 ? `${prefixCls.value}-item-left` : `${prefixCls.value}-item-right`; } if (props.mode === 'left') return `${prefixCls.value}-item-left`; if (props.mode === 'right') return `${prefixCls.value}-item-right`; if (eleProps.position === 'right') return `${prefixCls.value}-item-right`; return ''; };2. 交替布局(mode="alternate")
内容在时间轴两侧轮流出现,对应 demo/alternate.vue:
<a-timeline mode="alternate"> <a-timeline-item>Create a services site 2015-09-01</a-timeline-item> <a-timeline-item color="green">Solve initial network problems 2015-09-01</a-timeline-item> <a-timeline-item> <template #dot><ClockCircleOutlined style="font-size: 16px" /></template> Sed ut perspiciatis unde omnis iste natus error sit voluptatem... </a-timeline-item> <a-timeline-item color="red">Network problems being solved 2015-09-01</a-timeline-item> </a-timeline>从源码可见交替模式的放置规则:偶数下标(idx % 2 === 0)放左侧,奇数下标放右侧;若节点显式设置了position="left"或position="right",则优先遵循节点自身的位置声明。
3. 右侧布局(mode="right")
时间轴点移到内容右侧,对应 demo/right.vue:
<a-timeline mode="right"> <a-timeline-item>Create a services site 2015-09-01</a-timeline-item> <a-timeline-item> <template #dot><clock-circle-outlined style="font-size: 16px" /></template> Technical testing 2015-09-01 </a-timeline-item> </a-timeline>mode="right"会让所有节点都应用-item-right类;布局样式在 style/index.tsx 中通过insetInlineStart: calc(100% - ...)将 tail、head、head-custom 定位到右端。
4. 标签模式(label 属性触发)
自 3.0 版本起,Timeline.Item支持label属性,用于在时间轴另一侧单独展示时间,对应 demo/label.vue:
<a-radio-group v-model:value="mode" style="margin-bottom: 20px"> <a-radio value="left">Left</a-radio> <a-radio value="right">Right</a-radio> <a-radio value="alternate">Alternate</a-radio> </a-radio-group> <a-timeline :mode="mode"> <a-timeline-item label="2015-09-01">Create a services</a-timeline-item> <a-timeline-item label="2015-09-01 09:12:11">Solve initial network problems</a-timeline-item> <a-timeline-item>Technical testing</a-timeline-item> <a-timeline-item> <template #label><strong style="color: red">2015-09-01 09:12:11</strong></template> Network problems being solved </a-timeline-item> </a-timeline>关键点:label既支持普通字符串,也支持#label具名插槽(可插入自定义渲染,如红色加粗的时间文案)。从 Timeline.tsx 的源码可以看到,只要任意节点带有label,根节点就会追加-label样式类,进入标签布局模式:
const hasLabelItem = timeLineItems.some( item => !!(item.props?.label || item.children?.label), );标签模式下mode决定标签与内容的相对方位:left/alternate时标签在左、内容在右,右侧节点(-item-right)则反转——标签移到右半区、内容移到左半区,样式细节见 style/index.tsx。
四、幽灵节点(pending)与倒序(reverse)
幽灵节点:展示"进行中"状态
当任务仍在记录过程中,可以用幽灵节点标记当前进度,对应 demo/pending.vue:
<a-timeline pending="Recording..." :reverse="reverse"> <a-timeline-item>Create a services site 2015-09-01</a-timeline-item> <a-timeline-item>Solve initial network problems 2015-09-01</a-timeline-item> <a-timeline-item>Technical testing 2015-09-01</a-timeline-item> </a-timeline> <a-button type="primary" style="margin-top: 16px" @click="handleClick">Toggle Reverse</a-button>结合 Timeline.tsx 的实现,pending 的三种取值含义如下:
pending为真值(true):渲染幽灵节点,但内容为空;pending为字符串:字符串作为幽灵节点的内容展示(如"Recording...");pending为VNode / slot:可用于完全定制节点内容。
当pending为真时,内部会构造一个带pending={true}标记的TimelineItem:
const pendingItem = pending ? ( <TimelineItem pending={!!pending} dot={pendingDot || <LoadingOutlined />}> {pendingNode} </TimelineItem> ) : null;pendingDot用于定制幽灵节点的时间轴点,默认值是<LoadingOutlined />(加载图标),这也解释了为何幽灵节点默认带"加载中"的视觉暗示。幽灵节点的连接线渲染为虚线(dotted),样式见 style/index.tsx。
reverse 倒序排列
reverse为true时节点倒序显示(最新事件置顶,适合"最近发生在前"的诉求)。源码通过children.reverse()实现(Timeline.tsx):
const timeLineItems = reverse ? children.reverse() : children;倒序时样式上会做对应调整:-reverse类下最后一个节点的 tail 隐藏,而幽灵节点(pending)的 tail 以虚线重新出现,见 style/index.tsx,保证倒序后视觉上仍然连贯。
最后一个节点(last)的自动识别
Timeline会自动为最后一个节点追加-item-last类(Timeline.tsx):
const itemsCount = timeLineItems.length; const lastCls = `${prefixCls.value}-item-last`; const items = timeLineItems.map((ele, idx) => { const pendingClass = idx === itemsCount - 2 ? lastCls : ''; const readyClass = idx === itemsCount - 1 ? lastCls : ''; return cloneVNode(ele, { class: classNames([ !reverse && !!pending ? pendingClass : readyClass, getPositionCls(ele, idx), ]), }); });- 未倒序且有 pending:倒数第二个节点获得
-item-last(因为最后一个位置被幽灵节点占据); - 其他情况:最后一个节点获得
-item-last。
-item-last的样式会隐藏该节点的 tail 连接线,避免尾部出现悬空的线头(style/index.tsx)。
五、节点样式定制:color 与 dot
color:圆点颜色
color支持语义色名与任意自定义色值:
- 内置色名:
blue(默认,表示进行中/默认状态)、green(已完成/成功)、red(告警/错误)、gray(禁用/不可用); - 任意合法 CSS 色值:如
#00CCFF。
源码实现(TimelineItem.tsx):只有匹配blue|red|green|gray时才使用语义类名,否则按自定义色值走内联样式:
const customColor = computed(() => /blue|red|green|gray/.test(props.color || '') ? undefined : props.color || 'blue', ); const dotClassName = computed(() => ({ [`${prefixCls.value}-item-head`]: true, [`${prefixCls.value}-item-head-${props.color || 'blue'}`]: !customColor.value, })); // 渲染时:style={{ borderColor: customColor.value, color: customColor.value }}对应演示见 demo/color.vue,其中还演示了自定义色值#00CCFF与#dot插槽(SmileOutlined)的组合用法。内置色名映射到主题 token:blue → colorPrimary、red → colorError、green → colorSuccess、gray → colorTextDisabled(style/index.tsx)。
dot:自定义时间轴点
dot可以是字符串或插槽,通常传入图标实现更丰富的视觉表达,对应 demo/custom.vue:
<a-timeline-item color="red"> <template #dot><clock-circle-outlined style="font-size: 16px" /></template> Technical testing 2015-09-01 </a-timeline-item>当存在自定义 dot 时,head 会追加-item-head-custom类,样式将圆形默认点替换为自适应宽高的内容容器,并居中定位(style/index.tsx),因此图标可以自由缩放而不会撑破布局。
六、样式体系与主题定制
Timeline 采用 ant-design-vue 的 CSS-in-JS 样式方案,通过genComponentStyleHook('Timeline', ...)注册(style/index.tsx),并定义了如下设计 token:
| Token | 默认值 | 含义 |
|---|---|---|
| timeLineItemPaddingBottom | token.padding * 1.25 | 节点底部间距 |
| timeLineItemHeadSize | 10 | 时间轴点尺寸 |
| timeLineItemCustomHeadPaddingVertical | token.paddingXXS | 自定义轴点垂直内边距 |
| timeLineItemTailWidth | token.lineWidthBold | 连接线宽度 |
| timeLineHeadBorderWidth | wireframe 模式为lineWidthBold,否则lineWidth * 3 | 圆点边框宽度 |
组件的 class 前缀通过useConfigInject('timeline', props)注入,因此可通过ConfigProvider的prefixCls或主题 token 统一定制;同时支持-rtl类实现 RTL 方向适配(style/index.tsx)。所有根节点样式类均带hashId,保证样式隔离。
七、类型定义与测试保障
Timeline 导出完整的 TypeScript 类型:TimelineProps、TimelineItemProps(index.tsx),其中TimelineProps['mode']可直接用于约束变量类型(见 demo/label.vue 中的ref<TimelineProps['mode']>('left'))。
测试方面,tests/index.test.js 通过mountTest对Timeline及其Item子组件执行挂载与卸载冒烟测试,tests/demo.test.js 则对全部 demo 进行渲染快照校验,确保各布局、pending、reverse 场景的输出稳定。
八、实战小结
综合以上内容,使用 Timeline 时的核心决策路径可归纳为:
- 选整体布局:默认
left;事件较多且想均衡两侧空间用alternate;轴点靠右用right;需要单独突出时间信息用label(3.0+); - 标记状态:用
color(green/red/gray/自定义色值)区分完成、告警、禁用状态; - 展示进行中:设置
pending(true / 字符串 / VNode)并配合pendingDot定制幽灵轴点; - 调整阅读顺序:
reverse为true时倒序展示,常用于"最新动态置顶"场景; - 个性表达:用
dot插槽(图标)与position按节点微调位置。
所有能力均有对应的 demo 示例、源码实现(Timeline.tsx、TimelineItem.tsx)与样式定义(style/index.tsx)可供深入研读与直接复用。
【免费下载链接】ant-design-vue🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜项目地址: https://gitcode.com/gh_mirrors/an/ant-design-vue
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考