React实现短信验证码输入组件
在日常开发中,短信验证码输入是一个非常常见的需求。今天和大家分享一个基于React实现的验证码输入组件,它具有以下特点:
- 支持6位数字验证码输入
- 自动聚焦下一个输入框
- 支持回退删除
- 支持移动端输入
- 输入完成后自动触发回调
组件代码实现
const SmsVerify = ({
onComplete,
onChange
}: {
onComplete?: (code: string) => void
onChange?: (value: string) => void
}) => {
const [code, setCode, getCode] = useGetState<string[]>([])
const inputRefs = useRef<(HTMLInputElement | null)[]>([])
useEffect(() => {
const seat = new Array(6).fill('')
setCode(seat)
}, [])
useEffect(() => {
// 当所有格子都填满时触发完成回调
if (code.every((v) => v !== '') && onComplete) {
onComplete(code.join(''))
}
onChange?.(code.join(''))
}, [code, onComplete])
const handleOnChange = ({
value,
index
}: {
value: string | number
index: number
}) => {
// 将value转换为字符串并确保只保留数字
const stringValue = String(value).replace(/[^0-9]/g, '')
// 只取第一个数字
const singleDigit = stringValue.slice(0, 1)
if (singleDigit) {
setCode(
produce((draft) => {
draft[index] = singleDigit
})
)
// 自动聚焦下一个输入框
if (index < 5) {
inputRefs.current[index + 1]?.focus()
}
}
}
const handleKeyDown = (
e: React.KeyboardEvent<HTMLInputElement>,
index: number
) => {
if (e.key === 'Backspace') {
// 当前格子为空时,删除键将焦点移到上一个输入框
setCode(
produce((draft) => {
draft[index] = ''
})
)
inputRefs.current[index - 1]?.focus()
e.preventDefault()
}
}
return (
<div className="sms-verify">
<div className="flex gap-[0.1rem]">
{code.map((value, index) => {
return (
<InputNumber
className={classNames('text-[0.4rem]', { 'has-content': value })}
ref={(el) => {
if (el) {
inputRefs.current[index] = el
}
}}
type="tel"
value={value}
key={'T-' + index}
controls={false}
onKeyDown={(e) => handleKeyDown(e, index)}
onInput={(value) =>
handleOnChange({ value: value || '', index })
}
/>
)
})}
</div>
</div>
)
}
关键点
- 使用 type="tel" 调起数字键盘,如果把type类型换成number,在移动端会有兼容性问题,用户可以输入特殊字符和中文,用type="tel",则不会有这个情况
- onInput 代替onChange事件,如果用onChange,最后一个输入框可以无限制输入内容,删除内容时,无法删除输入的全部内容,而使用onInput 时,能一次性删除当前输入框所有内容
愿你走出半生,归来仍是少年

浙公网安备 33010602011771号