React中验证码输入框自动切换焦点的优化方案咨询
React验证码输入框自动焦点切换优化方案
方案一:单个容器Ref + 索引控制焦点
这种方案无需给每个输入框单独设置Ref,只需要给包裹输入框的容器加一个Ref,通过容器的children属性定位并切换焦点,同时结合受控组件统一管理验证码状态。
示例代码:
import { useState, useRef } from "react"; function CodeInput() { const CODE_LENGTH = 5; const [code, setCode] = useState(new Array(CODE_LENGTH).fill("")); const inputContainerRef = useRef(null); const handleInputChange = (e, index) => { // 仅允许输入字母数字 const value = e.target.value.replace(/[^0-9a-zA-Z]/g, ""); if (!value) return; const newCode = [...code]; newCode[index] = value; setCode(newCode); // 输入完成后自动聚焦下一个输入框 if (index < CODE_LENGTH - 1) { inputContainerRef.current.children[index + 1].focus(); } }; const handleKeyDown = (e, index) => { // 退格时,当前输入框为空则聚焦上一个并清空内容 if (e.key === "Backspace" && !code[index]) { e.preventDefault(); if (index > 0) { inputContainerRef.current.children[index - 1].focus(); const newCode = [...code]; newCode[index - 1] = ""; setCode(newCode); } } }; return ( <div ref={inputContainerRef} style={{ display: "flex", gap: "8px" }}> {code.map((char, index) => ( <input key={index} type="text" maxLength={1} value={char} onChange={(e) => handleInputChange(e, index)} onKeyDown={(e) => handleKeyDown(e, index)} style={{ width: "40px", height: "40px", textAlign: "center", fontSize: "18px" }} /> ))} </div> ); } export default CodeInput;
优势:
- 仅需一个容器Ref,避免手动创建多个独立Ref的繁琐
- 验证码状态完全由React State管理,避免DOM操作导致的状态不一致
- 扩展性强:修改验证码长度只需调整
CODE_LENGTH常量,无需改动其他逻辑
方案二:动态数组Ref管理
通过useRef创建一个数组存储每个输入框的Ref,动态关联输入框,相比手动创建多个Ref更简洁,适合需要单独控制某个输入框的场景。
示例代码:
import { useState, useRef } from "react"; function CodeInput() { const CODE_LENGTH = 5; const [code, setCode] = useState(new Array(CODE_LENGTH).fill("")); const inputRefs = useRef([]); const handleInputChange = (e, index) => { const value = e.target.value.replace(/[^0-9a-zA-Z]/g, ""); if (!value) return; const newCode = [...code]; newCode[index] = value; setCode(newCode); if (index < CODE_LENGTH - 1) { inputRefs.current[index + 1].focus(); } }; const handleKeyDown = (e, index) => { if (e.key === "Backspace" && !code[index]) { e.preventDefault(); if (index > 0) { inputRefs.current[index - 1].focus(); const newCode = [...code]; newCode[index - 1] = ""; setCode(newCode); } } }; return ( <div style={{ display: "flex", gap: "8px" }}> {code.map((char, index) => ( <input key={index} ref={(el) => (inputRefs.current[index] = el)} type="text" maxLength={1} value={char} onChange={(e) => handleInputChange(e, index)} onKeyDown={(e) => handleKeyDown(e, index)} style={{ width: "40px", height: "40px", textAlign: "center", fontSize: "18px" }} /> ))} </div> ); } export default CodeInput;
优势:
- 动态关联输入框Ref,逻辑清晰,可直接访问任意位置的输入框
- 结合受控组件,状态管理更可靠
- 代码结构简洁,易于维护
方案对比
两种方案都比直接操作DOM或手动创建多个独立Ref更优雅:
- 容器Ref方案代码更轻量化,无需给每个输入框绑定Ref
- 数组Ref方案更灵活,适合需要对单个输入框做额外操作的场景
内容的提问来源于stack exchange,提问作者Cor4zon
相关产品推荐
相关产品推荐

