思路是写出用于展示密码的div(比如四位的密码那就是4个div),在div上面写一个实际的input控制输入,再设置input不可见。上代码
import React, { useEffect, useRef, useState } from "react";
import './index.scss';
interface IInputOTP {
length: number;
handleInputDone: Function;
password: string;
}
const InputOTP = (props: IInputOTP) => {
const prefixCls = 'input-OTP';
const { handleInputDone, length, password, keyCode } = props
const KEYCODE = keyCode
const PIN_LENGTH = length;
const [value, setValue] = useState("");
const inputRef = useRef(null);
useEffect(() => {
setValue(password)
}, [password])
const handleClick = (e: any) => {
e.preventDefault();
if (inputRef.current) {
inputRef.current.focus();
}
}
const handleChange = (e: any) => {
let reg=/^[0-9]+.?[0-9]*$/
if (e.target.value.length <= PIN_LENGTH) {
if (e.target.value.length > 0 && reg.test(e.target.value) || e.target.value.length === 0) {
const val = e.target.value || "";
setValue(val);
if (e.target.value.length === PIN_LENGTH) {
handleInputDone(val)
}
} else {
return
}
} else {
return
}
}
// 处理一些键盘特殊按键,清除默认行为
const handleOnKeyDown = (e: any) => {
switch (e.keyCode) {
case keyCode.LEFT_ARROW:
case keyCode.RIGHT_ARROW:
case keyCode.HOME:
case keyCode.END:
case keyCode.SPACE:
e.preventDefault();
break;
default:
break;
}
}
return (
<div className={prefixCls}>
<input
ref={inputRef}
className={`${prefixCls}-hiddenInput`}
type="tel"
pattern="[0-9]*"
onChange={handleChange}
onKeyDown={handleOnKeyDown}
value={value}
autoFocus
/>
{Array.from({ length: PIN_LENGTH }).map((_, index) => {
const focus =
index === value.length ||
(index === PIN_LENGTH - 1 && value.length === PIN_LENGTH);
return (
<input
className={`${prefixCls}-pinInput ${focus ? `${prefixCls}-fucos` : null}`}
key={index}
value={value[index]? '∗' : ''}
onClick={handleClick}
readOnly={true}
/>
);
})}
</div>
);
}
export default InputOTP;
.input-OTP {
display: flex;
width: 100%;
flex-wrap: nowrap;
justify-content: center;
&-hiddenInput {
color: transparent;
outline: none;
padding: 0;
border-width: 0;
box-shadow: none;
position: absolute;
caret-color: transparent;
text-shadow: 0 0 0 #000;
margin-left: -200%
}
&-pinInput {
box-sizing: border-box;
padding: 0;
outline: none;
background-color: transparent;
width: 120px;
height: 120px;
background: #EBEBEB;
color: #000000;
font-size: 52px;
border-radius: 24px;
border: none;
margin-right: 24px;
text-align: center;
line-height: 120px;
}
&-fucos {
border-color: orangered;
border-width: 2px;
}
}