使用JavaScript正则在React输入框实时格式化驾照号码的修改问题
实现方案
核心格式化逻辑
实现思路如下:
- 先对用户输入做预处理:自动转为大写,移除所有非字母、数字的字符(包括之前插入的分隔符,避免重复拼接)
- 采用范围匹配的正则分组,无需等待全量输入完成,只要对应段有内容就插入分隔符
核心格式化函数代码:
const formatLicenseNumber = (input) => { // 预处理:仅保留大写字母和数字,过滤其他所有字符 const cleaned = input.toUpperCase().replace(/[^A-Z0-9]/g, ''); // 分组匹配:前2位字母、接下来3位字母、最后最多6位数字 const match = cleaned.match(/^([A-Z]{0,2})([A-Z]{0,3})([0-9]{0,6})$/); if (!match) return cleaned; // 过滤空分组后用-拼接 return match.slice(1).filter(Boolean).join('-'); }
可直接测试格式化效果:
- 输入
DLHGK→ 输出DL-HGK - 输入
DLHGK12→ 输出DL-HGK-12 - 输入
dLhgK123456→ 自动转大写输出DL-HGK-123456
React 组件完整实现
额外增加了光标位置修复逻辑,解决实时格式化导致的光标自动跳转到末尾的问题:
import { useRef, useState } from 'react'; const LicenseInput = () => { const [value, setValue] = useState(''); const inputRef = useRef(null); const handleChange = (e) => { const input = e.target; const cursorPosition = input.selectionStart; const rawValue = input.value; // 计算格式化前光标位置对应的有效字符数(排除分隔符) const rawValidCharCount = rawValue.slice(0, cursorPosition).replace(/[^A-Z0-9]/g, '').length; const formatted = formatLicenseNumber(rawValue); setValue(formatted); // 计算格式化后对应的光标位置 let newCursorPos = 0; let validCount = 0; for (let i = 0; i < formatted.length; i++) { if (/[A-Z0-9]/.test(formatted[i])) { validCount++; } newCursorPos++; if (validCount === rawValidCharCount) { break; } } // 异步更新光标位置,避免React渲染覆盖 requestAnimationFrame(() => { if (inputRef.current) { inputRef.current.selectionStart = inputRef.current.selectionEnd = newCursorPos; } }); }; return ( <input ref={inputRef} value={value} onChange={handleChange} placeholder="请输入驾照号码" maxLength={13} // 总长度:2位+分隔符+3位+分隔符+6位=13位 /> ); }; const formatLicenseNumber = (input) => { const cleaned = input.toUpperCase().replace(/[^A-Z0-9]/g, ''); const match = cleaned.match(/^([A-Z]{0,2})([A-Z]{0,3})([0-9]{0,6})$/); if (!match) return cleaned; return match.slice(1).filter(Boolean).join('-'); }; export default LicenseInput;
内容的提问来源于stack exchange,提问作者Tanish Raj
相关产品推荐
相关产品推荐

