从零实现一个灵活可扩展的Steps步骤条组件
项目初期的技术选型
最近刚做完一个内部管理系统,里面用到了不少组件库的组件。其中有个功能是用户提交审批流程,设计稿里明确要求要有步骤条来显示当前进度。当时我第一反应是用 Ant Design 的 Steps 组件,毕竟它功能齐全,文档也够详细。
不过在实际开发前,我也纠结了一下要不要自己写个简单的步骤条组件。后来考虑到时间成本和维护性,还是决定用现成的。毕竟自己写的组件后续还得处理各种兼容性和样式问题,实在划不来。
最大的坑:动态步骤更新
开始用 Ant Design 的 Steps 挺顺利的,基本配置很快就搞定了。但很快我就遇到了第一个大坑:当用户点击“上一步”或“下一步”按钮时,步骤条需要实时更新当前状态,同时还要同步更新表单内容。
我的初始实现是直接通过 React 的 state 来控制当前步骤的索引值,代码大概是这样的:
import React, { useState } from 'react';
import { Steps, Button } from 'antd';
const { Step } = Steps;
const MySteps = () => {
const [current, setCurrent] = useState(0);
const next = () => {
setCurrent(current + 1);
};
const prev = () => {
setCurrent(current - 1);
};
return (
<div>
<Steps current={current}>
<Step title="第一步" />
<Step title="第二步" />
<Step title="第三步" />
</Steps>
<div style={{ marginTop: 20 }}>
{current > 0 && <Button onClick={prev}>上一步</Button>}
{current < 2 && <Button onClick={next}>下一步</Button>}
</div>
</div>
);
};
export default MySteps;
看起来没啥问题吧?结果测试的时候发现,当快速连续点击“下一步”按钮时,步骤条的状态会乱掉!比如本来应该从第一步跳到第二步,但有时候会直接跳到第三步。
折腾了半天才发现,问题出在异步更新上。React 的 setState 是异步的,所以如果用户快速点击按钮,state 的更新就会滞后,导致逻辑混乱。
最终的解决方案
为了解决这个问题,我调整了代码逻辑,确保每次点击按钮时都能正确地等待上一次的 state 更新完成再执行下一次操作。下面是改进后的代码:
import React, { useState } from 'react';
import { Steps, Button } from 'antd';
const { Step } = Steps;
const MySteps = () => {
const [current, setCurrent] = useState(0);
const next = () => {
setCurrent((prevCurrent) => {
const newCurrent = prevCurrent + 1;
if (newCurrent <= 2) {
// 这里可以添加一些额外的逻辑,比如表单验证
return newCurrent;
}
return prevCurrent;
});
};
const prev = () => {
setCurrent((prevCurrent) => {
const newCurrent = prevCurrent - 1;
if (newCurrent >= 0) {
return newCurrent;
}
return prevCurrent;
});
};
return (
<div>
<Steps current={current}>
<Step title="第一步" />
<Step title="第二步" />
<Step title="第三步" />
</Steps>
<div style={{ marginTop: 20 }}>
{current > 0 && <Button onClick={prev}>上一步</Button>}
{current < 2 && <Button onClick={next}>下一步</Button>}
</div>
</div>
);
};
export default MySteps;
核心改动就是使用函数式 setState,这样可以确保每次状态更新都基于最新的 state 值,避免了异步更新带来的问题。
这里提醒一下:如果在项目中遇到类似的异步状态更新问题,优先考虑函数式 setState,亲测有效!
踩坑提醒:样式适配问题
解决了动态更新的问题后,我又遇到了另一个小麻烦:Ant Design 的 Steps 默认样式在某些分辨率下会显得特别拥挤,尤其是在小屏幕设备上。
起初我尝试通过修改全局样式来调整,但发现这样会影响其他页面的 Steps 样式。最后我选择用 CSS 的 scoped 样式来单独处理这个问题:
.my-steps .ant-steps-item {
margin-right: 10px;
}
.my-steps .ant-steps-item-title {
font-size: 14px;
}
然后在组件里加上类名:
<Steps current={current} className="my-steps">
<Step title="第一步" />
<Step title="第二步" />
<Step title="第三步" />
</Steps>
虽然这不是最优雅的解法,但至少解决了眼前的问题。
回顾与反思
总的来说,这次用 Steps 步骤条的经历还算顺利,但也让我意识到一些需要注意的地方:
- 动态状态更新一定要小心异步问题,尤其是涉及到用户交互的部分。
- 样式适配是个老生常谈的问题,但在实际项目中还是会频繁出现。尽量用 scoped 样式来避免全局污染。
- 虽然用现成的组件库能省不少事,但还是要对底层原理有一定的了解,不然遇到问题就容易抓瞎。
目前这个实现还有一些小瑕疵,比如在某些极端情况下,步骤条的动画效果会有点卡顿,但因为影响不大,暂时就没花时间去优化了。
结尾
以上是我个人对这个 Steps 步骤条组件的完整讲解,有更优的实现方式欢迎评论区交流。其实每个项目都会有一些意想不到的小坑,关键是要学会总结经验,下次再遇到类似问题就能更快解决了。
这个技巧的拓展用法还有很多,比如结合后端接口动态生成步骤条,或者在移动端做适配优化。后续我会继续分享这类博客,希望能帮到更多开发者。

暂无评论