Ant Design Progress 与 Steps 组合教程:3 种模式搞定多步骤进度展示

发布时间:2026/10/25 1:41:06
Ant Design Progress 与 Steps 组合教程:3 种模式搞定多步骤进度展示

Ant Design Progress 与 Steps 组合教程:3 种模式搞定多步骤进度展示

【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/antde/ant-design

用 Ant Design 的 Progress(进度条)和 Steps(步骤条)搭出「整体进度 + 步骤明细」的进度指示器:本文给出选型对比、3 种可复制的组合模式、样式与交互打磨,以及一个完整的多步骤表单示例,读完即可直接落到项目里。

选型速查:Progress 还是 Steps 📌

结论先行:只需一个百分比时用 Progress;任务有阶段划分用 Steps;既要总体又要明细,就把两者组合。对比如下:

组件适用场景核心属性属性说明
Progress单一任务耗时展示:上传、导出、数据处理percent百分比,0–100,决定填充长度
type取line/circle/dashboard,决定形态
steps分段进度设置,把一条进度切成分段
Steps有先后阶段的流程:注册、下单、审批current当前步骤下标,从 0 开始,驱动步骤状态
percent当前步骤的完成百分比,只作用于current指向的步骤
items步骤数组,每项含title、description
status步骤状态,取wait/process/finish/error

判断标准很简单:信息是「一个数字」还是「一条流程」。两者都不够时才需要组合,这正是后两节的主题。

单组件快速上手

先分别确认两个组件的最短写法,后面组合时就不用回头查基础属性。

Progress 进度条快速上手

这段演示 Progress 的线性与圆形两种基础形态:

import { Progress } from 'antd'; <Progress percent={60} /> <Progress type="circle" percent={75} />

适合文件上传、报表导出这类只有一个百分比的长耗时任务。关键点:percent直接控制填充比例,type只负责换形态,两者互不影响。线性进度的更多属性(status、showInfo等)可参考 components/progress/demo/line.md,圆形进度见 components/progress/demo/circle.md。

Steps 步骤条快速上手

这段演示 Steps 的最短可运行写法:

import { Steps } from 'antd'; <Steps current={1} items={[ { title: '填写订单' }, { title: '支付' }, { title: '发货' }, ]} />

适合引导用户按流程走完多个阶段,步骤数据整体传给items。关键点:current指定用户走到第几步,它之前的步骤自动变为完成态,之后的保持等待态。步骤切换的完整交互可参考 components/steps/demo/step-next.md。

三种组合模式

3 种模式的组合逻辑一致:Progress 负责输出百分比,Steps 负责呈现阶段明细,区别只在「百分比放在哪一层」。按业务需要三选一即可。

模式 A:宏观 + 微观双信息层

原理一句话:顶部 Progress 用「已完成步骤数 ÷ 总步骤数」算出整体进度,下方 Steps 展示步骤明细。

import { Progress, Steps } from 'antd'; function TaskProgress() { const currentStep = 1; // 当前在第 2 步(从 0 计数) const totalSteps = 3; // 宏观进度:走到第几步就占几分 const overall = Math.round((currentStep / totalSteps) * 100); return ( <div> <Progress percent={overall} size="small" style={{ marginBottom: 16 }} /> <Steps current={currentStep} percent={60} // 微观进度:当前步骤内部已完成 60% items={[ { title: '信息填写', description: '基本信息填写' }, { title: '资料审核', description: '等待审核' }, { title: '完成注册' }, ]} /> </div> ); }

关键点:这里有两个进度数——顶部的整体百分比是宏观层,Steps 的percent是微观层,且只作用于current指向的那一步,两者互不覆盖。

模式 B:步骤内嵌子进度

原理一句话:把 Progress 塞进 Steps 的描述区,让每一步内部再显示自己的子任务进度。

import { Steps, Progress } from 'antd'; const stepData = [ { title: '用户信息', percent: 100 }, { title: '账户安全', percent: 60 }, { title: '服务协议', percent: 0 }, ]; function NestedProgress() { const currentStep = 1; return ( <Steps current={currentStep} items={stepData.map((s) => ({ title: s.title, description: <Progress percent={s.percent} size="small" />, }))} /> ); }

关键点:description接收任意 React 节点,所以可以直接替换成一条迷你 Progress,每步一条互不影响,适合步骤内部还有多个子任务的场景。

模式 C:环形汇总型

原理一句话:用圆形 Progress 做整体汇总,旁边放 Steps 做明细,形成「汇总 + 明细」的仪表盘式布局。

import { Progress, Steps } from 'antd'; const steps = [ { title: '准备', percent: 100 }, { title: '处理', percent: 75 }, { title: '完成', percent: 0 }, ]; function RingSummary() { // 每步等权重:整体进度 = 各步进度之和 ÷ 步数 const overall = steps.reduce((sum, s) => sum + s.percent / steps.length, 0); const current = steps.findIndex((s) => s.percent < 100); return ( <div style={{ display: 'flex', gap: 32, alignItems: 'center' }}> <Progress type="circle" percent={Math.round(overall)} width={120} /> <Steps current={current === -1 ? steps.length - 1 : current} items={steps.map((s) => ({ title: s.title }))} /> </div> ); }

关键点:整体百分比是各步进度的加权平均,子任务每完成一点环就跟着走,比模式 A 的「按步骤跳格」更平滑;current取第一个未完成的步骤下标,全部完成时钳制在最后一步。

细节打磨

三种模式落地后,通常还要调颜色、指示器与尺寸三处,下面是常用做法。

颜色定制。strokeColor控制进度条填充色,可传色值、渐变对象,也可以按进度值分段变色,让进度自带状态含义:

// 按进度分段变色:低红、中黄、高绿 const color = percent < 30 ? '#f5222d' : percent < 70 ? '#faad14' : '#52c41a'; <Progress percent={percent} strokeColor={color} /> // 渐变填充 <Progress percent={90} strokeColor={{ from: '#108ee9', to: '#87d068' }} />

自定义步骤指示器。progressDot把默认的圆形指示点换成自定义节点,常用来挂 Popover 展示悬浮详情:

import { Popover } from 'antd'; <Steps current={1} progressDot={(dot, { status, index }) => ( <Popover content={`第 ${index + 1} 步状态:${status}`}>{dot}</Popover> )} items={[{ title: '步骤 1' }, { title: '步骤 2' }, { title: '步骤 3' }]} />

尺寸与响应式。次要区域(如表格行内、侧边栏)统一缩小两个组件的体量:Steps 传size="small",Progress 传size="small"并调小strokeWidth,迷你步骤条的写法见 components/steps/demo/small-size.md。需要自适应屏幕时,在resize监听里判断window.innerWidth < 768后切换small/default即可,初始渲染时执行一次监听回调,避免首次布局错位。

完整示例:多步骤表单

下面是一个三步注册流程:基本信息 → 账户安全 → 完成注册。整体进度不由current决定,而是每一步各自维护 0–100 的进度,再按等权重汇总成总进度。

import { useState } from 'react'; import { Steps, Progress, Button, Card, Form, Input, Checkbox } from 'antd'; const TITLES = ['基本信息', '账户安全', '完成注册']; function RegisterFlow() { const [form] = Form.useForm(); const [current, setCurrent] = useState(0); // 每一步的进度(0-100),整体进度从它汇总而来 const [stepProgress, setStepProgress] = useState([0, 0, 0]); // 整体进度:各步等权重,求和后除以步数 const overall = stepProgress.reduce((sum, p) => sum + p / 100, 0) * (100 / TITLES.length); // 只更新某一步的进度,避免整体重算时状态串位 const setStep = (index, percent) => setStepProgress((prev) => prev.map((p, i) => (i === index ? percent : p))); // 第一步:两个表单项各占 50% const onBasicChange = () => { const v = form.getFieldsValue(); const filled = [v.username, v.email].filter(Boolean).length; setStep(0, filled * 50); }; // 第二步:密码填写占 50% const onSecurityChange = () => { setStep(1, form.getFieldValue('password') ? 50 : 0); }; const next = () => form.validateFields().then(() => { setStep(current, 100); // 当前步先置满再前进 setCurrent(current + 1); }); const submit = () => form.validateFields().then((values) => { setStep(2, 100); console.log('注册数据:', values); // 此处发送请求到服务端 }); return ( <div style={{ maxWidth: 800, margin: '0 auto' }}> {/* 顶部整体进度 + 下方步骤明细,两者同源于 stepProgress */} <Progress percent={Math.round(overall)} size="small" style={{ marginBottom: 16 }} /> <Steps current={current} items={TITLES.map((t, i) => ({ title: t, description: i < current ? '已完成' : i === current ? '进行中' : '未开始', }))} /> <Card style={{ marginTop: 32 }}> <Form form={form} layout="vertical" onValuesChange={current === 0 ? onBasicChange : current === 1 ? onSecurityChange : undefined} > {current === 0 && ( <> <Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}> <Input /> </Form.Item> <Form.Item name="email" label="邮箱" rules={[{ required: true, type: 'email', message: '请输入正确的邮箱' }]}> <Input /> </Form.Item> </> )} {current === 1 && ( <> <Form.Item name="password" label="密码" rules={[{ required: true, message: '请输入密码' }]}> <Input.Password /> </Form.Item> <Form.Item name="confirm" label="确认密码" dependencies={['password']} rules={[ { required: true, message: '请确认密码' }, ({ getFieldValue }) => ({ validator: (_, v) => !v || v === getFieldValue('password') ? Promise.resolve() : Promise.reject('两次密码输入不一致'), }), ]} > <Input.Password /> </Form.Item> </> )} {current === 2 && ( <Form.Item name="agreement" valuePropName="checked"> <Checkbox onChange={(e) => setStep(2, e.target.checked ? 100 : 0)}> 我已阅读并同意服务条款 </Checkbox> </Form.Item> )} </Form> </Card> <div style={{ textAlign: 'right', marginTop: 16 }}> {current > 0 && ( <Button style={{ marginRight: 8 }} onClick={() => setCurrent(current - 1)}>上一步</Button> )} {current < TITLES.length - 1 ? ( <Button type="primary" onClick={next}>下一步</Button> ) : ( <Button type="primary" onClick={submit}>提交</Button> )} </div> </div> ); }

关键点:整体进度 = 各步进度之和 ÷ 步数。例如第一步完成(100)、第二步填了一半(50)时,总进度为 (100 + 50 + 0) / 3 ≈ 50%,而不是current变化才跳格;stepProgress是唯一数据源,顶部 Progress 和下方 Steps 都由它派生,保证两处永远一致。

收尾清单 ✅

  • 只有一个百分比就用 Progress 单组件,别为了「完整」硬上 Steps
  • 整体进度与各步进度共用同一份状态(如stepProgress数组),不要维护两份会走散的数值
  • 整体进度按各步进度加权汇总,而不是按current下标跳变
  • 同一页面统一 Progress 与 Steps 的颜色和尺寸,次要区域用size="small"
  • 步骤出错时给该步设status="error"、Progress 设status="exception",给用户明确的状态反馈

【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/antde/ant-design

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考