自定义Antd InputNumber组件:HH:MM转分钟及失焦问题求助
自定义Antd InputNumber组件问题排查与改进方案
问题原因分析
- parser逻辑漏洞:用户输入过程中(如未输入冒号时),
split(':')仅返回单个元素,parseInt(minutes)会得到NaN,导致返回值异常,触发组件重渲染失焦。 - max值配置错误:当前
max设为24/168(小时单位),但组件value存储的是分钟数,单位不匹配引发数值校验异常,导致组件状态混乱失焦。 - value处理不当:
currentValue || 0会将0转为0,但formatter处理0时返回空字符串,显示值与实际值不匹配,触发组件重渲染。 - 字符串比较错误:parser中直接用字符串比较
hours > 24,字符串按字符编码比较会出现逻辑错误(如"3">"24"会返回true),需转数字后再判断。
改进后的完整代码
import React from 'react' import { Col, InputNumber, Row } from 'antd' function MinutesInput({ value: currentValue, onChange, type = 'daily', ...props }) { const getMaxMinutes = () => { return type === 'daily' ? 24 * 60 : 168 * 60 } return ( <Row> <Col span={24}> <InputNumber className="w-100" min={0} max={getMaxMinutes()} formatter={(value) => { if (value === 0) { return '00:00' } if (!value) { return '' } const hours = Math.floor(value / 60) const minutes = value % 60 return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}` }} parser={(value) => { if (!value) return 0 // 处理输入过程中的不完整格式(如仅输入数字、未输入冒号) const parts = value.split(':') let hours = parseInt(parts[0]) || 0 let minutes = parseInt(parts[1]) || 0 // 分钟数限制在0-59之间 minutes = Math.max(0, Math.min(59, minutes)) // 小时数限制在对应类型的最大值内 const maxHours = type === 'daily' ? 24 : 168 hours = Math.max(0, Math.min(maxHours, hours)) // 当小时等于最大值时,分钟强制设为0 if (hours === maxHours) { minutes = 0 } return hours * 60 + minutes }} value={currentValue ?? 0} addonAfter={currentValue !== undefined && currentValue !== 0 ? `${Math.floor(currentValue / 60)}h ${currentValue % 60}m` : ''} onChange={onChange} {...props} /> </Col> </Row> ) } export default MinutesInput
关键优化点说明
- 修正max值单位:将max改为分钟数(2460=1440、16860=10080),与value的存储单位一致,避免校验异常。
- 完善parser容错逻辑:
- 处理输入不完整的情况(如仅输入数字、无冒号),默认分钟为0,避免NaN。
- 限制分钟在0-59之间,小时在对应类型的最大值内,当小时达到最大值时,分钟强制设为0(避免出现24:30这种非法值)。
- 将字符串转为数字后再进行大小比较,避免字符串比较的逻辑错误。
- 优化value与formatter的一致性:
- 用
currentValue ?? 0替代currentValue || 0,避免0被错误覆盖。 - formatter处理0时返回"00:00",保证显示与值的一致性,避免组件状态混乱。
- 用
padStart(2, '0')统一格式为两位数字,提升用户体验。
- 用
- 优化addonAfter显示:当currentValue为0或undefined时,不显示附加文本,避免冗余信息。
内容的提问来源于stack exchange,提问作者WildThing
相关产品推荐
相关产品推荐

