期望实现的效果
主要功能
1、进入页面自动触发发送短信验证码;
2、手机系统如果支持自动识别短信验证码,就自动填充;
3、支持手动输入短信验证码;
4、点击数字框,弹起数字键盘,输入数字后,边框变为绿色,继续下一个数字框输入数字。。。直到六个数字输入完毕,方可继续下一步操作
实现思路
1、利用 触发 input 控件 的焦点事件可以唤起手机自带的软键盘特性,弹起数字键盘;
2、绑定input控件的onchange事件,更新 input控件的合法值和6个数字框数字显示;
3、使用IOS高版本系统支持的input属性,实现自动识别短信验证码。
核心代码
Html部分
// 展示部分
<div className="number-boxs">
{codeArray.map((v, i) => {
return (
<div
className={classnames('item-content', { active: !!v })}
key={i}
onClick={handleNumberItemClick}
>
{v}
</div>
)
})}
</div>
// 输入部分
<div className="input-box-wrap">
<input
type="text"
value={inputValue}
onChange={hanldeInputCodeChange}
pattern="[0-9]*"
autoComplete="one-time-code"
inputMode="numeric"
maxLength={6}
ref={inputRef}
/>
</div>
Js 逻辑
// 有6个空字符的数组
const defaultCodeArray = new Array(6).fill('')
// 6个验证码数组
const [codeArray, setCodeArray] = useState(defaultCodeArray)
// 输入框的合法值
const [inputValue, setInputValue] = useState('')
const inputRef = useRef(null)
// 验证码为真的新数组
const codeArrayReal = codeArray.filter((v) => v)
// 输入框change
const hanldeInputCodeChange = (e) => {
let value = e.target.value
let tempValue = value.replace(/[^0-9]/g, '').substr(0, 6)
let tempArray = [...tempValue]
let tempCodeArray = codeArray.map((v, i) => (v = tempArray[i] || ''))
setInputValue(tempValue)
setCodeArray(tempCodeArray)
}
const handleNumberItemClick = () => {
inputRef.current.focus()
}
Less
.number-boxs {
margin: 43px 0 24px;
display: flex;
justify-content: space-between;
.item-content {
width: 48px;
height: 54px;
background: #F5F5F5;
border-radius: 8px;
&.active {
border: 1px solid #33CB98;
}
}
}
遇到的问题
1、获取input控件的焦点事件;
控件隐藏后,无法获取焦点事件,使用opacity: 0解决;
2、 设置type属性弹起数字键盘
// 安卓支持
<input type="number" />
<input type="tel" />
// ios
<input type="number" pattern="number" /> // 输入.+-和数字
<input type="number" pattern="[0-9]*" /> // 只能输入数字+-
3、弹起数字键盘;
<input
type="text"
inputmode="numeric"
pattern="\d{6}"
/>
4、onchange事件
// type="number", 输入值不合法时,value就变成空啦
<input type="number" pattern="[0-9]*" onchange=(e => console.log(e)) />
5、自动识别短信验证码 引用的资料
使用该功能前提是手机已经授权开启了自动识别短信验证码功能,例如:ios开如何开启,jingyan.baidu.com/article/fd8…
<input
type="text"
inputmode="numeric"
autocomplete="one-time-code"
pattern="\d{6}"
/>