没啥特别的技术,就是记录一下自己开发时遇到的问题和解决方案,以后自己查看着方便
简介
自定义的车牌号键盘
效果
要实现一个方便输入车牌号的键盘和输入框,支持新能源车牌。
最开始的想法是用多个小程序的input输入框实现,但是发现了一个很不爽的体验,每个的输入框聚焦都会引发手机键盘的弹出,emmmm,这可不是我要的效果。
最终的实现方案就是 没用到一个input输入框,全部使用的div实现输入框效果。将键盘选中的内容存到一个数组里,输入框里展示对应数组的文字。
我把它写成一个component,方便多页面使用
wxml文件
复制代码 请录入车牌号 { {carNumArr[index] || ''}} { {item}} { {item}} { {item}} { {item}} { {item}} { {item}}
js代码
const INPUT_NUM = 8;//车牌号输入框个数const EmptyArray = new Array(INPUT_NUM).fill('');//['','','','','','','','']// 车牌输入框的下标const INPUT_INDEX = { FIRST: 0, SECOND: 1};Component({ data: { // 键 provinceArr: ['京', '沪', '津', '苏', '粤', '冀', '晋', '蒙', '辽', '吉', '黑', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘', '桂', '琼', '渝', '川', '贵', '云', '藏', '陕', '甘', '青', '宁', '新', '港', '澳', '台'], strArrOne: ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'P'], strArrTwo: ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'], strArrThree: ['Z', 'X', 'C', 'V', 'B', 'N', 'M'], numArr: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], hiddenPro: false, // 隐藏省份键盘 hiddenStr: true, // 隐藏数字字母键盘 carNumArr: EmptyArray, selectInputIndex: 0, btnDisabled: true }, methods: { proTap(e) { //点击省份 let province = e.currentTarget.dataset.province; const { carNumArr, selectInputIndex } = this.data; this.setData({ hiddenPro: true, hiddenStr: false }); carNumArr[selectInputIndex] = province; // 选择车牌号时触发 this.setData({ carNumArr, // 选中一个后,下一个输入框聚焦 selectInputIndex: selectInputIndex !== carNumArr.length - 1 ? selectInputIndex + 1 : selectInputIndex, btnDisabled: this.btnDisabled() }); }, strTap(e) { //点击字母数字 const str = e.currentTarget.dataset.str; const { carNumArr, selectInputIndex } = this.data; carNumArr[selectInputIndex] = str; this.setData({ carNumArr, // 选中一个后,下一个输入框聚焦 selectInputIndex: selectInputIndex !== carNumArr.length - 1 ? selectInputIndex + 1 : selectInputIndex, btnDisabled: this.btnDisabled() }); }, inputCarNum(e) { const { index } = e.currentTarget.dataset; this.setData({ showCarKeyboard: true, selectInputIndex: index }); if (index === INPUT_INDEX.FIRST) { // 第一个输入框展示省份键盘,第二个展示字母数字输入框(数字不可点),以后就是数字字母输入框(都可点) this.setData({ hiddenPro: false, hiddenStr: true }); } else if (index === INPUT_INDEX.SECOND) { this.setData({ hiddenPro: true, hiddenStr: false }); } else { this.setData({ hiddenPro: true, hiddenStr: false }); } }, backSpace() { //删除 const { carNumArr, selectInputIndex } = this.data; carNumArr[selectInputIndex] = ''; this.setData({ carNumArr, selectInputIndex: selectInputIndex !== INPUT_INDEX.FIRST ? selectInputIndex - 1 : selectInputIndex, btnDisabled: this.btnDisabled() }, () => { if (this.data.selectInputIndex === INPUT_INDEX.FIRST) { //这里必须要用this.data.selectInputIndex,用最新的 this.setData({ hiddenPro: false, hiddenStr: true }); } }); }, // 只有输入内容的车牌号位数合法时,展示确认按钮 btnDisabled() { const { carNumArr } = this.data; const disabled = carNumArr.some((item, index) => { if (index !== carNumArr.length - 1) { return !item; } return false; }); return disabled; }, onCancel() { this.setData({ carNumArr: EmptyArray }); this.triggerEvent('onCancel'); }, onOk() { const carNum = this.data.carNumArr.join(''); this.triggerEvent('onOk', carNum); } },});复制代码
wxss文件
/* 键盘 */.keyboard { width: 100%; position: fixed; bottom: 0; left:0; z-index: 1000; background-color: rgba(210, 213, 219, 90);}.fl { float: left}.carnum { text-align: center; height: 88rpx}.tel { border-bottom: 2rpx solid #ddd; height: 100rpx; line-height: 100rpx;}.provinces { overflow: hidden; padding-top: 20rpx;}.pro-li { font-size: 32rpx; color: #353535; height: 76rpx; width: 62rpx; line-height: 76rpx; text-align: center; margin-left: 12rpx; margin-bottom: 20rpx; background-color: #fff; box-shadow: 0px 1rpx 2rpx 0 #979797; border-radius: 5px; flex: 1}.keyNums .disabled { background-color: #F7F7F7; color: #CCC}.keyNums { overflow: hidden; padding-top: 20rpx; display: flex; flex-direction: column;}.keyNums .row { display: flex;}.keyNums .numRow { padding: 0 10rpx;}.keyNums .strOne { padding: 0 10rpx;}.keyNums .strOne .strOneItem { flex: 1}.keyNums .strTwo { padding: 0 40rpx;}.keyNums .strOne .strTwoItem { flex: 1}.keyNums .strThree { padding-left: 116rpx; padding-right: 10rpx;}.keyNums .strOne .strThreeItem { flex: 1}.keyNums .strOne .strThreeItem:nth-child(7) { margin-left: 100px}.keyNums .pro-li:nth-child(16) { color: red}.keyNums .strThree .kb-del { margin-left: 12rpx}.keyNums .strThree .kb-icon { flex: 1.5; background: #ABB3BD; margin-left: 40rpx;}/* modal样式 */.modal-box { width: 100%; position: absolute; top: 0; bottom: 0; display: flex; align-items: center; justify-content: center;}.modal-wrapper { margin: 30% 30rpx; height: 380rpx; padding: 30rpx; background-color: #fff; border-radius: 10rpx; z-index: 300; position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; align-content: space-between; justify-content: space-between; overflow: hidden; text-align: left;}.modal-wrapper .model-btn-group { display: flex; box-sizing: border-box; font-size: 32rpx;}.model-btn-group view { width: 50%; text-align: center; box-sizing: border-box;}.model-btn-group .btn { flex: 1; font-size: 18px}.model-btn-group .cancel { color: #999;}.model-btn-group .confirm { color: #fff; background-color: #ff5000;}.model-btn-group .confirm.active { opacity: 1;}.modal-cover { width: 100%; background-color: #242424; opacity: 0.5; z-index: 299; position: fixed; top: 0; left: 0; bottom: 0; right: 0; margin: auto; overflow: hidden;}.modal-input { display: flex;}.modal-input .input { border: 1px solid #979797; margin-right:6rpx; border-radius: 3px; flex: 1; text-align: center; padding: 8px; height: 22px;}.modal-input .input:nth-child(1) { border-right-width: 0; margin-right: 0; position: relative; border-bottom-right-radius: 0; border-top-right-radius: 0;}.modal-input .input:nth-child(1)::after { content: ""; position: absolute; right: -1px; width: 1px; height: 20px; background-color: #979797; z-index: -10}.modal-input .input:nth-child(2) { position: relative; border-left-width: 0; margin-right:20rpx; border-bottom-left-radius: 0; border-top-left-radius: 0;}.modal-input .input:nth-child(2)::after { content: ""; position: absolute; right:-16rpx; top: 45%; width: 5px; height: 5px; border-radius: 50%; background-color: #979797}.modal-input .input:nth-child(8) { border: 1px dashed #979797;}.modal-input .activeInput { border-radius: 3px !important; border: 1px solid #FF5000 !important}.modal-input .text { text-align: right; color: #c5c5c5; font-size: 28rpx;}.modal-placeholder-class { color: #c5c5c5;}.modal-title { display: flex; font-size: 20px; color: #333333}.titleWrapper { flex: 1;}.title-text { font-size: 18px; font-weight: bold;}.iconWrapper { flex: 1; text-align: right;}.close-icon { width: 35rpx; height: 35rpx;}.delete-icon { width: 55rpx; height: 40rpx; margin-top: 18rpx;}复制代码
json文件,标识出来这是一个component
{ "component": true}复制代码
在页面里如何使用呢
要在json里引用组件
{ "usingComponents": { "carKeyboard": "/components/carKeyboard/carKeyboard" }}复制代码
复制代码
//index.jsPage({ data: { carnum: '', showKeyboard:false, }, inputCarNum() { this.setData({ showKeyboard: true}) }, onOk(e){ console.log(e.detail,'输入的车牌号') }, onCancel(){ this.setData({ showKeyboard: false }) }})复制代码