近期遇到一个需求, 是要求做一个验证码的输入框, 设计图如下
最开始是毫无思路的, 于是去看了下相关案例了解下. 了解下了两种大概的思路,
- 通过
linear-gradient
来对输入框进行样式修改, 下面是我找到的一个StackoveFlow的实现方式
css
input[type="text"] {
border: solid 1px dimgrey;
width: 400px;
background: repeating-linear-gradient(90deg, #ffffff 0px, #ffffff 19px, #000000 20px);
color: dimgrey;
font-family: monospace;
letter-spacing: 1.75ch;
padding-left: 0.8ch;
}
input:focus {
outline: none;
color: dodgerblue;
}
html
<label for="name">Name:</label>
<input type="text" id="name" name="name" maxlength="20" />
- 另外一种则是通过控制focus来进行处理, 下面是我通过这种方式封装的组件
tsx
import {Input, View} from "@tarojs/components";
import Taro, {Component} from "@tarojs/taro";
import './index.scss'
type OwnProps ={
value: string
onInput: (val?: string) => void
}
export default class CodeInput extends Component<OwnProps> {
public state = {
focus: false,
}
render() {
const computeClass = (index) => !!this.props.value[index] ? 'codeInput__code codeInput__code--active' : 'codeInput__code'
return (
<View className='codeInput'>
{
Array.from({ length: 6 }).map((_, index) => (
<View className={computeClass(index)} onClick={() => this.setState({ focus: true })}>
{this.props.value[index]}
</View>
))
}
<Input
className='codeInput__input'
focus={this.state.focus}
value={this.props.value}
onInput={(e: any) => this.props.onInput(e.target.value)}
maxLength={6}
/>
</View>
)
}
}
scss
.codeInput {
font-size: 34px;
position: relative;
display: flex;
}
.codeInput__code {
width: 82px;
height: 82px;
line-height: 82px;
text-align: center;
margin-left: 22px;
display: inline-block;
border: 1PX solid #DFDFDF;
&:first-of-type {
margin-left: 0;
}
&--active {
border-color: $font-color;
}
}
.codeInput__input {
position: absolute;
top: 22px;
left: 32px;
opacity: 0;
letter-spacing: 92px;
}
其思路就在于需要通过控制对验证码框的点击, 触发对透明输入框的focus, 用户的实际输入也就会到输入框里, 这时候每个小框再通过对应的下标获取到相应的值.
样式方面需要注意处理的是 letter-spacing
, 如果没有处理, 则会导致 用户输入时的光标与对应的小框位置不匹配.