如何在单字符长度的OTP(计时器)输入框中覆盖已填充的字符?
如何在单字符长度的OTP(计时器)输入框中覆盖已填充的字符?
我完全懂你遇到的这个麻烦——现在每个单字符输入框填完内容后,得手动按退格键删掉旧字符才能输入新的,用起来特别不顺手。咱们可以通过两个小调整来解决这个问题:
解决思路
- 自动选中输入框内容:当输入框获得焦点时,自动选中里面已有的字符,这样用户输入新内容时会直接覆盖旧值。
- 优化输入处理逻辑:确保在输入有效数字时,不管输入框原本有没有内容,都直接替换成新输入的值,同时正常处理焦点跳转。
修改后的代码
咱们来调整你的React组件代码,把这两个优化加进去:
const { useState, useRef } = React; function App() { const [time, setTime] = useState(null); const [running, setRunning] = useState(false); const [editState, setEditState] = useState(false); const [hms, setHms] = useState(Array(6).fill(0)); const inputs = useRef([]); const handleChange = (e, idx) => { const {value} = e.target; // 只要输入的是单个数字,就直接替换,不管原有内容 if (value.match(/^\d$/)) { const newHms = [...hms]; newHms[idx] = value; setHms(newHms); // 输入完成后跳转到下一个输入框,避免越界 if (idx < 5) { inputs.current[idx+1].focus(); } } } const handleKeyDown = (e, idx) => { if (e.key === 'Backspace') { const newHms = [...hms]; // 如果当前输入框有内容,先清空 if (newHms[idx] !== '') { newHms[idx] = ''; setHms(newHms); } else if (idx > 0) { // 空的话就跳转到上一个输入框 inputs.current[idx - 1].focus(); } } } // 新增:输入框获得焦点时选中内容 const handleFocus = (e) => { e.target.select(); } return ( <> <div id='root' style={{backgroundColor: "#e3b23c", width:"400px", height:"400px"}}> {true && <div> { hms.map((_, idx) => { return ( <span key={idx}> <input type='text' maxLength="1" value={hms[idx]} onKeyDown={(e) => handleKeyDown(e, idx)} onChange={(e) => handleChange(e, idx)} onFocus={handleFocus} {/* 绑定焦点事件 */} ref={(el) => (inputs.current[idx] = el)} style={{width: '40px', height: '40px', margin: '0 5px', textAlign: 'center', fontSize: '18px', border: '1px solid #ccc', borderRadius: '4px'} } /> {(idx == 1 || idx == 3) && <span style={{ fontWeight: 600, fontSize: "30px" }}>:</span>} </span> ); }) } </div>} <div> Hours : Minutes : Seconds </div> </div> </> ) } ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div>
关键修改说明
- 新增了
handleFocus函数并绑定到input的onFocus事件,当输入框获得焦点时自动选中内部内容,用户输入新字符就会直接覆盖旧值。 - 调整了
handleChange里的焦点跳转判断:把idx < 6改成idx < 5,因为hms数组是6个元素(索引0到5),避免出现越界访问的问题。 - 优化了
handleChange的逻辑,只要输入的是单个数字,就直接替换原有值,不再受输入框原有内容的限制。
这样修改后,不管输入框有没有填过内容,只要切换到这个输入框,输入新的数字就会直接覆盖旧值,用起来就跟常见的OTP输入框一样顺手啦!
备注:内容来源于stack exchange,提问作者M. Varun Reddy
相关产品推荐
相关产品推荐

