车牌号的虚拟键盘实现
直接上代码吧,逻辑不复杂,就是繁琐
component组件:
import React, { Component } from 'react';
import { Icon } from 'components';
class LicensePlate extends Component {
constructor(props) {
super(props);
this.state = {
value: this.props.value||"",//直接使用props.value会在点击提交时,无法保存组件状态。建议使用setValue
showkeyboard: false,
marking: 0,
nowId: null,
val0: '',
val2: '',
val3: '',
val4: '',
val5: '',
val6: '',
val7: '',
chineseList: [
{ name: '京', id: 1 },
{ name: '津', id: 2 },
{ name: '冀', id: 3 },
{ name: '晋', id: 4 },
{ name: '蒙', id: 5 },
{ name: '辽', id: 6 },
{ name: '吉', id: 7 },
{ name: '黑', id: 8 },
{ name: '沪', id: 9 },
{ name: '苏', id: 10 },
{ name: '浙', id: 11 },
{ name: '皖', id: 12 },
{ name: '闽', id: 13 },
{ name: '赣', id: 14 },
{ name: '鲁', id: 15 },
{ name: '豫', id: 16 },
{ name: '鄂', id: 17 },
{ name: '湘', id: 18 },
{ name: '粤', id: 19 },
{ name: '桂', id: 20 },
{ name: '琼', id: 21 },
{ name: '渝', id: 22 },
{ name: '川', id: 23 },
{ name: '贵', id: 24 },
{ name: '云', id: 25 },
// { name: '藏', id: 26 },
{ name: '陕', id: 27 },
{ name: '甘', id: 28 },
{ name: '青', id: 29 },
{ name: '宁', id: 30 },
{ name: '新', id: 31 },
{ name: '藏', id: 32 },
{ name: '使', id: 33 },
{ name: '领', id: 34 },
{ name: '警', id: 35 },
{ name: '学', id: 36 },
{ name: '港', id: 37 },
{ name: '澳', id: 38 },
{ name: '', id: 99 },
],
englishNumber: [
{ name: '1', id: 28 },
{ name: '2', id: 29 },
{ name: '3', id: 30 },
{ name: '4', id: 31 },
{ name: '5', id: 32 },
{ name: '6', id: 33 },
{ name: '7', id: 34 },
{ name: '8', id: 35 },
{ name: '9', id: 36 },
{ name: '0', id: 37 },
{ name: 'Q', id: 38 },
{ name: 'W', id: 39 },
{ name: 'E', id: 40 },
{ name: 'R', id: 41 },
{ name: 'T', id: 42 },
{ name: 'Y', id: 43 },
{ name: 'U', id: 44 },
{ name: 'I', id: 45 },
{ name: 'O', id: 46 },
{ name: 'P', id: 47 },
{ name: 'A', id: 48 },
{ name: 'S', id: 49 },
{ name: 'D', id: 50 },
{ name: 'F', id: 51 },
{ name: 'G', id: 52 },
{ name: 'H', id: 53 },
{ name: 'J', id: 54 },
{ name: 'K', id: 55 },
{ name: 'L', id: 56 },
{ name: 'Z', id: 57 },
{ name: 'X', id: 58 },
{ name: 'C', id: 59 },
{ name: 'V', id: 60 },
{ name: 'B', id: 61 },
{ name: 'N', id: 62 },
{ name: 'M', id: 63 },
{ name: '', id: 99 },
],
};
}
onClickFocus(e) {
this.setState({
marking: e.target.title*1
})
this.keyboardShow()
}
onConfirm() {
let { val0,val1,val2,val3,val4,val5,val6,val7}=this.state
this.keyboardHide()
this.setState({
value:val0+val1+val2+val3+val4+val5+val6+val7,
})
}
// 清空,供外部调用
clearValue() {
this.setState({
value: ''
})
}
//获取,供外部调用
getValue() {
return this.state.value
}
//获取值
setValue(val) {
let obj = {}
for (let i = 0; i < val.length; i++) {
obj[`val${i}`]=val.slice(i,i+1)
}
this.setState({
value: val,
...obj
});
}
onChangeFocus(e) {
if (e.target.title == 45 || e.target.title == 46) {//点击o和i无效化
return
}
let nowId = e.target.title
if (e.target.title == 99) {//回格
let obj2={}
let { marking } = this.state
obj2[`val${marking}`] =''
this.setState({
value: this.state.value.substring(0, this.state.value.length - 1),
nowId,
marking:this.state.marking==0?this.state.marking: --marking,
...obj2
})
return
}
let obj = {}
switch (this.state.marking) {//字符串转换
case 0:
obj.val0 = e.target.accessKey
break;
case 1:
obj.val1 = e.target.accessKey
break;
case 2:
obj.val2 = e.target.accessKey
break;
case 3:
obj.val3 = e.target.accessKey
break;
case 4:
obj.val4 = e.target.accessKey
break;
case 5:
obj.val5 = e.target.accessKey
break;
case 6:
obj.val6 = e.target.accessKey
break;
case 7:
obj.val7 = e.target.accessKey
break;
default:
break;
}
this.setState({
nowId,
marking: this.state.marking>6?this.state.marking: ++this.state.marking,
...obj
})
}
renderPasswordGrid() {
let length = this.props.length;
let htmls = [];
let marking = this.state.marking;
for (let i = 0; i < length; i++) {
let classN = this.state.val0==''&&i==0?"color":"";
let el = (
<div key={i} title={i} className={[ marking == i ? `${classN} activeColor passwordHolder` : `${classN} passwordHolder`]}>
{ this.state.val0==''&&i==0?"省":this.state[`val${i}`]}
</div>
)
//最后的新能源是否显示
if (i == length - 1 && marking < 7 && this.state.val7=='') {
el = (
<div key={i} title={i} className="last" > <div title={i} className="last1" >新</div><div className="last2" title={i}>能源</div> </div>
)
}
htmls.push(el);
}
return htmls;
}
keyboardHide() {
this.setState({
showkeyboard: false
})
}
keyboardShow() {
this.setState({
showkeyboard: true
})
}
render() {
let { chineseList, englishNumber, showkeyboard, nowId } = this.state;
let dataList = this.state.marking==0 ? chineseList : englishNumber
return (
<div>
<div className="passwordGrid" >
<div className="passwordGridItemWrap" onClick={(e) => this.onClickFocus(e)}>{this.renderPasswordGrid()}
</div>
</div>
{showkeyboard &&
<div className="keyboard-box" >
{
dataList.map((item) => {
let disabled = item.id == 45 || item.id == 46 ? "disabled" : ""
return (<div key={item.id} className={item.id == 99 ? "back cont-box " : nowId == item.id ? "cont-box active" : ` cont-box ${disabled}`}
title={item.id} accessKey={item.name} onClick={(e) => this.onChangeFocus(e)} >
{item.name}
{item.id == 99 && <Icon name={"shanchu1"} size={22} title={99} />}
</div>)
})
}
<div className="confirm" onClick={(e) => this.onConfirm(e)} >确定</div>
</div>
}
</div>
)
}
}
LicensePlate.defaultProps = {
length: 8
}
export default LicensePlate;
CSS样式:
.passwordGrid{
.passwordGridItemWrap{
font-weight: 500;
font-size: 40px;
.passwordHolder{
width: 73px;
height: 88px;
background: #F0F2F5;
border: 1px solid #E6E7EB;
border-radius: 8px;
line-height: inherit;
margin-right: 5px;
}
.activeColor{
background: #FFF2F0;
border: 1px solid #FB5B3B;
}
.color{
color: #BABDC2;
}
.last{
width: 73px;
height: 88px;
position:absolute;
background: #F0FFF0;
border: 1px solid #79E083;
border-radius: 8px;
display: inline-flex;
right: 0;
align-items: center;
flex-direction: column;
font-size: 12px;
color: #79E083;
margin-right: 8px;
.last1{
position: absolute;
top: -16%;
font-size: 24px;
}
.last2{
position: absolute;
top: 20%;
font-size: 24px;
}
}
}
}
.keyboard-box{
position: absolute;
bottom: 0;
left: 0;
height: 480px;
width: 100%;
background:#E1E2E6;
padding-left: 16px;
padding-top: 76px;
.cont-box{
width: 61px;
height: 88px;
margin-right: 12px;
display: inline-block;
background: #FFFFFF;
border-radius: 8px;
text-align: center;
margin-bottom: 16px;
}
.cont-box:nth-child(31){
margin-left: 36px;
}
.active{
background: #FB5B3B;
color: #FFFFFF;
}
.disabled{
color: #CCCCCC;
}
.confirm{
position: absolute;
top: 0;
right: 50px;
}
.back {
width: 134px ;
}
}
效果: