快速现金按键场景下的数字替换逻辑实现求助
解决方案
问题根源
你的现有代码使用lastIndexOf('0')每次替换字符串最后一个0,导致1000.00按2后变成1000.02,与预期的1002.00不符;同时未处理“输入0后再按其他数字时仅覆盖该0”的逻辑。
实现方案
我们需要提前标记快速现金数值中需要替换的0的位置,并通过指针跟踪当前替换位置,根据输入数字类型决定是否移动指针:
- 添加状态:跟踪可替换的0的索引列表,以及当前替换的位置指针。
- 快速现金选中逻辑:仅标记整数部分最后一个0和小数部分的所有0(匹配你的示例需求)。
- 键盘输入处理:替换指针指向的0,输入非0时移动指针,输入0时保持指针位置以便后续覆盖。
修改后的完整代码
import { useState, useCallback } from 'react'; const CashInput = () => { const [isQuickCash, setIsQuickCash] = useState(false); const [selectedValues, setSelectedValues] = useState(''); // 新增状态:可替换的0的索引列表、当前替换位置指针 const [replaceableIndices, setReplaceableIndices] = useState<number[]>([]); const [currentReplaceIdx, setCurrentReplaceIdx] = useState<number>(0); // 快速现金按键点击处理 const handleQuickCash = (amount: string) => { setIsQuickCash(true); setSelectedValues(amount); const [integerPart, decimalPart] = amount.split('.'); // 仅收集整数部分最后一个0的索引 const lastIntegerZeroIdx = integerPart.lastIndexOf('0'); const integerZeroIndices = lastIntegerZeroIdx !== -1 ? [lastIntegerZeroIdx] : []; // 收集小数部分所有0的索引(需加上整数部分长度+1,对应原字符串中的位置) const decimalZeroIndices = [...decimalPart] .map((char, idx) => char === '0' ? integerPart.length + 1 + idx : -1) .filter(idx => idx !== -1); // 合并索引:先替换整数最后一个0,再替换小数部分的0 setReplaceableIndices([...integerZeroIndices, ...decimalZeroIndices]); setCurrentReplaceIdx(0); }; // 键盘按键处理 const handleKeypadButton = useCallback( (value: string) => { if (value === 'C') { setIsQuickCash(false); setSelectedValues(''); setReplaceableIndices([]); setCurrentReplaceIdx(0); } else if (value === '.') { setSelectedValues((prev) => { const str = prev?.toString() || ''; return str.includes('.') ? str : str + value; }); } else if (isQuickCash) { setSelectedValues((prev) => { // 无可用替换位置时,直接追加输入 if (replaceableIndices.length === 0 || currentReplaceIdx >= replaceableIndices.length) { return prev + value; } const charArr = prev.split(''); const targetIdx = replaceableIndices[currentReplaceIdx]; // 替换目标位置的0 charArr[targetIdx] = value; const newStr = charArr.join(''); // 输入非0数字时,移动指针到下一个替换位置 if (value !== '0') { setCurrentReplaceIdx(prevIdx => prevIdx + 1); } return newStr; }); } else { setSelectedValues(prev => (prev || '') + value); } }, [isQuickCash, replaceableIndices, currentReplaceIdx], ); // 组件渲染示例 return ( <div> <div>当前金额:{selectedValues || '0.00'}</div> <button onClick={() => handleQuickCash('1000.00')}>1000.00</button> <button onClick={() => handleQuickCash('500.00')}>500.00</button> <div className="keypad"> {['1','2','3','4','5','6','7','8','9','0','.','C'].map(key => ( <button key={key} onClick={() => handleKeypadButton(key)}>{key}</button> ))} </div> </div> ); }; export default CashInput;
测试验证
选中1000.00后依次按2、0、8:
- 按2 → 替换整数最后一个0,得到1002.00,指针移动到小数第一个0的位置。
- 按0 → 替换小数第一个0为0,指针保持不动。
- 按8 → 覆盖刚才输入的0为8,得到1002.08,指针移动到小数第二个0的位置。
完全符合你的需求。
内容的提问来源于stack exchange,提问作者Kaito Pader
相关产品推荐
相关产品推荐

