如何在onBlur触发时为数字输入框添加%符号
问题描述
我有一个用于输入数字的输入框,需要在onBlur事件触发时为输入的数字添加%符号。当前使用的处理函数如下:
const onBlurValue = (day_index, value) => { const newBreakDownMonths = [...breakDownMonths]; const day = newBreakDownMonths[nowMonth].break_down_days[day_index]; if(value == "") { day.value = 0; } else { day.value = value; } setChangedDay(day); }
该函数的作用是:当onBlur触发时,若输入框为空则将值设为0,否则保存输入的数字。自定义输入组件代码如下:
<Input inputProps={{ value: day.value, type: "number", step: "0.1", onKeyDown: (e) => detectKeyDown(e, day), onChange: (e) => onChangeValue(index, e.target.value), onFocus: (e) => onFocusValue(index, e.target.value), onBlur: (e) => onBlurValue(index, e.target.value), style: { marginTop: 0, }, }} />;
解决方案
由于type="number"的输入框无法显示非数字字符(比如%),需要分离数据存储值和输入框显示内容,同时处理聚焦/失焦时的内容转换,具体修改步骤如下:
1. 添加聚焦状态并修改输入框配置
首先在组件中添加状态跟踪输入框的聚焦状态,同时将输入框类型改为text,并根据聚焦状态切换显示内容:
// 新增状态:跟踪输入框是否处于聚焦状态 const [isFocused, setIsFocused] = useState(false);
修改后的Input组件代码:
<Input inputProps={{ // 失焦时显示带%的内容,聚焦时显示纯数字 value: isFocused ? day.value : (day.value === 0 ? "0%" : `${day.value}%`), type: "text", // 改为text类型以支持显示%符号 step: "0.1", onKeyDown: (e) => detectKeyDown(e, day), onChange: (e) => { // 移除输入内容中的%,只保留数字部分用于更新 const cleanValue = e.target.value.replace(/%/g, ""); onChangeValue(index, cleanValue); }, onFocus: (e) => { // 聚焦时移除内容中的%,恢复纯数字输入状态 const cleanValue = e.target.value.replace(/%/g, ""); onFocusValue(index, cleanValue); setIsFocused(true); }, onBlur: (e) => { // 失焦时先清理内容中的%,再传入处理函数 const cleanValue = e.target.value.replace(/%/g, ""); onBlurValue(index, cleanValue); setIsFocused(false); }, style: { marginTop: 0, }, }} />;
2. 优化onBlurValue处理函数
确保存储的是纯数字,同时兼容空值或非数字输入的情况:
const onBlurValue = (day_index, value) => { const newBreakDownMonths = [...breakDownMonths]; const day = newBreakDownMonths[nowMonth].break_down_days[day_index]; // 处理空值、非数字输入,统一转为0 const numValue = value === "" || isNaN(Number(value)) ? 0 : Number(value); day.value = numValue; setChangedDay(day); }
3. 同步修改onChangeValue函数(可选)
如果onChangeValue是实时更新存储值,同样需要确保只存储纯数字:
const onChangeValue = (index, value) => { const cleanValue = value.replace(/%/g, ""); const numValue = cleanValue === "" || isNaN(Number(cleanValue)) ? 0 : Number(cleanValue); // 执行你的状态更新逻辑... }
内容的提问来源于stack exchange,提问作者Homeprogrammer312
相关产品推荐
相关产品推荐

