微信小程序车牌号输入组件(虚拟键盘)
本文参考 微信小程序中实现车牌输入功能, 进行了更加细致的键盘划分、删除等功能文中给出代码都是截图,完整代码在文末贴出。组件效果组件功能:其中虚拟键盘、新能源车牌等功能均可使用封装成一个组件可以直接 Import 使用可以给定默认初始值(如 gif 中所示)父组件通过 change 事件可以监听到车牌号每一次的变化组件部分样式也可以给定 class 来自定义可以规范用户输入车牌号,防止乱输引起的数
本文参考 微信小程序中实现车牌输入功能, 进行了更加细致的键盘划分、删除等功能
文中给出代码都是截图,完整代码在文末贴出。
组件效果
组件功能:
- 其中虚拟键盘、新能源车牌等功能均可使用
- 封装成一个组件可以直接 Import 使用
- 可以给定默认初始值(如 gif 中所示)
- 父组件通过 change 事件可以监听到车牌号每一次的变化
- 组件部分样式也可以给定 class 来自定义
- 可以规范用户输入车牌号,防止乱输引起的数据库错乱
组件思路
- 根据车牌号的规则,根据不同的第几位生成键盘
例如:第一位为省份简称
第二位为各省份地区编码
后面几位为普通 数字和部分字母组合,字母中不包括 i 和 o ,此处也是我百度之后才发现这个规律。
最后一位有字母数字之类的,也有一些特殊的字,比如 “港”, “澳”, “学”, “挂”, “警”
所以一共有四中键盘类型。
- 让当前输入框高亮,这样容易辨别。
- 给定车牌号的渲染数据为数组,这样可以一连串显示,最后通过 join 方法转换成 字符串,并告知父组件变化。显示默认车牌的时候,用 split 方法 转换成数组给当前显示赋值。这样保证输入和输出的数据都是字符串,但是其实是利用数组完成的。
- 当前输入完成后,自动跳转到下一输入框。当前内容删除后,自动跳转到上一输入框。并且要保证 虚拟键盘显示的内容与车牌规则保持一致。
这里主要利用的就是给定了一个参数,来告诉我点击到的是哪一个输入框,该显示哪一个虚拟键盘类型。
用省份显示为例
其他都是一样的处理方式,当普通几位显示的时候,不改变 虚拟键盘类型就可以了。
- 还在组件中加入了自定义类的功能,这样可以在父组件中修改样式,按需求定制。
在父组件中修改与否如下图所示:
组件代码(完整代码)
同款代码 demo 在: https://download.csdn.net/download/lb1135909273/54815362,当然是不付费的啦!
wxml:
<!--components/CarNumber/index.wxml-->
<!-- 车牌号输入框 -->
<view class="inputs custom-input-class">
<view class="inputs-item custom-item-class {{ currentInput === 0 ? 'item-active' : '' }}" bind:tap="showProvinceBoard">{{ carNum[0] }}</view>
<view class="inputs-item custom-item-class {{ currentInput === 1 ? 'item-active' : '' }}" bind:tap="showAreaBoard">{{ carNum[1] }}</view>
<view class="split">·</view>
<view class="inputs-item custom-item-class {{ currentInput === 2 ? 'item-active' : '' }}" bind:tap="showNumberBoard" data-index="{{ 2 }}">{{ carNum[2] }}</view>
<view class="inputs-item custom-item-class {{ currentInput === 3 ? 'item-active' : '' }}" bind:tap="showNumberBoard" data-index="{{ 3 }}">{{ carNum[3] }}</view>
<view class="inputs-item custom-item-class {{ currentInput === 4 ? 'item-active' : '' }}" bind:tap="showNumberBoard" data-index="{{ 4 }}">{{ carNum[4] }}</view>
<view class="inputs-item custom-item-class {{ currentInput === 5 ? 'item-active' : '' }}" bind:tap="showNumberBoard" data-index="{{ 5 }}">{{ carNum[5] }}</view>
<view class="inputs-item custom-item-class {{ currentInput === 6 ? 'item-active' : '' }}" bind:tap="showNumberBoard" data-index="{{ 6 }}">{{ carNum[6] }}</view>
<view wx:if="{{ !newEnergy }}" class="new-energy" bind:tap="changeCarToNewEnergy">
<image class="new-energy-img custom-energy-icon" src="../../statics/img/new_energy.png" />
</view>
<view wx:else class="inputs-item custom-item-class {{ currentInput === 7 ? 'item-active' : '' }}" bind:tap="showLastBoard">{{ carNum[7] }}</view>
</view>
<!-- 虚拟键盘 -->
<view class="keyboard" hidden="{{ !keyboard }}">
<view class="keyboardClose">
<view class="keyboardClose_btn" bindtap='closeKeyboard'>关闭</view>
</view>
<!-- 省份简写键盘 -->
<view class="keyboard-item" wx:if="{{ keyboardType === 1 }}">
<view class="keyboard-line" wx:for="{{ provinces }}" wx:key="index">
<view class="keyboard-btn" wx:for="{{ item }}" wx:key="index" data-val="{{ itemlist }}" wx:for-item="itemlist" bindtap='chooseProvince'>
{{ itemlist }}
</view>
</view>
<view class="keyboard-del" bindtap="delProvince">
<text>清除</text>
</view>
</view>
<!-- 地区简写键盘 -->
<view class="keyboard-item" wx:if="{{ keyboardType === 2 }}">
<view class="keyboard-line" wx:for="{{ areas }}" wx:key="index">
<view class="keyboard-btn" wx:for="{{ item }}" wx:key="index" data-val="{{ itemlist }}" wx:for-item="itemlist" bindtap='chooseArea'>
{{ itemlist }}
</view>
</view>
<view class="keyboard-del" bindtap='delArea'>
<text>清除</text>
</view>
</view>
<!-- 普通类型键盘 -->
<view class="keyboard-item" wx:if="{{ keyboardType === 3 }}">
<view class="keyboard-line" wx:for="{{ numbers }}" wx:key="index">
<view class="keyboard-btn" wx:for="{{ item }}" wx:key="index" data-val="{{ itemlist }}" wx:for-item="itemlist" bindtap='chooseNumber'>
{{ itemlist }}
</view>
</view>
<view class="keyboard-del" bindtap='delNumber'>
<text>清除</text>
</view>
</view>
<!-- 最后一位键盘 -->
<view class="keyboard-item" wx:if="{{ keyboardType === 4 }}">
<view class="keyboard-line" wx:for="{{ last }}" wx:key="index">
<view class="keyboard-btn" wx:for="{{ item }}" wx:key="index" data-val="{{ itemlist }}" wx:for-item="itemlist" bindtap='chooseLast'>
{{ itemlist }}
</view>
</view>
<view class="keyboard-del" bindtap='delLast'>
<text>清除</text>
</view>
</view>
</view>
wxss:
/* components/CarNumber/index.wxss */
.inputs {
display: flex;
align-items: center;
}
.split {
font-weight: bold;
}
.inputs-item {
border: 1rpx solid #333;
border-radius: 10%;
padding: 10rpx 0;
margin: 10rpx;
width: 65rpx;
font-size: 34rpx;
text-align: center;
height: 50rpx;
}
.new-energy {
display: flex;
align-items: center;
}
.new-energy-img{
height: 71rpx;
width: 68rpx;
margin: 10rpx;
border: none;
}
.item-active {
border: 5rpx solid #4b71fc;
color: #4b71fc;
}
.keyboard {
position: fixed;
bottom: 0;
/* height: 45vh; */
background-color: #d1d5d9;
width: 100%;
left: 0;
padding-bottom: 10rpx;
}
/* 关闭虚拟键盘 */
.keyboardClose {
height: 70rpx;
background-color: #f7f7f7;
overflow: hidden;
}
.keyboardClose_btn {
float: right;
line-height: 70rpx;
font-size: 15px;
padding-right: 30rpx;
}
.keyboard-line {
display: flex;
justify-content: center;
}
/* 虚拟键盘-单个按钮 */
.keyboard-btn {
font-size: 32rpx;
color: #333333;
background: #fff;
display: inline-block;
padding: 18rpx;
text-align: center;
box-shadow: 0 2rpx 0 0 #999999;
border-radius: 10rpx;
margin: 5rpx 6rpx;
}
/* 虚拟键盘-删除按钮 */
.keyboard-del {
font-size: 32rpx;
color: #333333;
background: #A7B0BC;
display: inline-block;
padding: 18rpx;
box-shadow: 0 2rpx 0 0 #999999;
border-radius: 10rpx;
margin: 5rpx;
position: absolute;
bottom: 10rpx;
right: 10rpx;
}
js:
// components/CarNumber/index.js
Component({
/**
* 自定义样式
*/
externalClasses: ['custom-input-class', 'custom-item-class', 'custom-energy-icon'],
/**
* 组件的属性列表
*/
properties: {
defaultNum: {
type: String,
default: ''
}
},
/**
* 页面展示
*/
pageLifetimes: {
show() {
if (this.data.defaultNum) {
// 存在默认车牌号
const length = this.data.defaultNum.length
if (length === 8) {
// 新能源车牌号
this.setData({
newEnergy: true
})
}
this.setData({
carNum: this.data.defaultNum.split('')
})
}
}
},
/**
* 组件的初始数据
*/
data: {
carNum: [],
currentInput: 0,
keyboard: false,
keyboardType: 1,
newEnergy: false,
// 省份输入
provinces: [
['京', '沪', '粤', '津', '冀', '晋', '蒙', '辽', '吉', '黑'],
['苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘'],
['桂', '琼', '渝', '川', '贵', '云', '藏'],
['陕', '甘', '青', '宁', '新'],
],
// 地区输入
areas: [
["A", "B", "C", "D", "E", "F", "G", "H", "J", "K"],
["L", "M", "N", "P", "Q", "R", "S", "T", "U", "V"],
["W", "X", "Y", "Z"]
],
// 车牌输入
numbers: [
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
["A", "B", "C", "D", "E", "F", "G", "H", "J", "K"],
["L", "M", "N", "P", "Q", "R", "S", "T", "U", "V"],
["W", "X", "Y", "Z"]
],
// 最后一位输入
last: [
["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
["A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", ],
["N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
["港", "澳", "学", "挂", "警"]
]
},
/**
* 组件的方法列表
*/
methods: {
/**
* 关闭键盘
*/
closeKeyboard() {
this.setData({
keyboard: false
})
},
/**
* 显示省份键盘
*/
showProvinceBoard() {
this.setData({
keyboard: true,
currentInput: 0,
keyboardType: 1
})
},
/**
* 确定选择省份
*/
chooseProvince(event) {
const { val } = event.currentTarget.dataset
this.setData({
'carNum[0]': val,
currentInput: 1,
keyboardType: 2
})
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 删除选定省份
*/
delProvince() {
this.setData({
'carNum[0]': ''
})
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 显示地区键盘
*/
showAreaBoard() {
this.setData({
keyboard: true,
currentInput: 1,
keyboardType: 2
})
},
/**
* 选定地区
*/
chooseArea(event) {
const { val } = event.currentTarget.dataset
this.setData({
'carNum[1]': val,
currentInput: 2,
keyboardType: 3
})
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 删除选定区域
*/
delArea() {
this.setData({
'carNum[1]': '',
currentInput: 0,
keyboardType: 1
})
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 显示普通键盘
*/
showNumberBoard(event) {
const { index } = event.currentTarget.dataset
const keyboardType = index === 6 && !this.data.newEnergy ? 4 : 3
this.setData({
keyboard: true,
currentInput: index,
keyboardType: keyboardType
})
},
/**
* 选定车牌
*/
chooseNumber(event) {
const { val } = event.currentTarget.dataset
const name = 'carNum[' + this.data.currentInput + ']'
this.setData({
[name]: val,
currentInput: this.data.currentInput + 1,
keyboardType: 3
})
// 跳到最后一位时,键盘不一样
if (this.data.currentInput === 6 && !this.data.newEnergy) {
this.setData({
keyboardType: 4
})
} else if (this.data.currentInput === 7 && this.data.newEnergy) {
this.setData({
keyboardType: 4
})
}
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 删除车牌
*/
delNumber() {
const name = 'carNum[' + this.data.currentInput + ']'
this.setData({
[name]: '',
currentInput: this.data.currentInput - 1,
keyboardType: 3
})
// 如果删除到地区时,切换键盘类型
if (this.data.currentInput === 1) {
this.setData({
keyboardType: 2
})
}
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 显示最后一位键盘
*/
showLastBoard() {
if (this.data.newEnergy) {
// 新能源
this.setData({
keyboard: true,
currentInput: 7,
keyboardType: 4
})
} else {
this.setData({
keyboard: true,
currentInput: 6,
keyboardType: 4
})
}
},
/**
* 选定最后一位
*/
chooseLast(event) {
const { val } = event.currentTarget.dataset
if (this.data.newEnergy) {
// 新能源
this.setData({
'carNum[7]': val,
currentInput: this.data.currentInput + 1,
keyboard: false
})
} else {
this.setData({
'carNum[6]': val,
currentInput: this.data.currentInput + 1,
keyboard: false
})
}
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 删除最后一位
*/
delLast() {
if (this.data.newEnergy) {
this.setData({
'carNum[7]': '',
currentInput: this.data.currentInput - 1,
keyboardType: 3
})
} else {
this.setData({
'carNum[6]': '',
currentInput: this.data.currentInput - 1,
keyboardType: 3
})
}
// 每次都触发 change 事件,通知父组件
this.triggerEvent('change', this.data.carNum.join(''))
},
/**
* 切换输入新能源车牌号
*/
changeCarToNewEnergy() {
this.setData({
newEnergy: true
})
}
}
})
以上内容均由自己编写,可能对车牌号规则等理解有误解,或者测试有问题的,欢迎联系、交流。
PS:其中用的新能源的图片来自于 https://frontendmasters.com/sale/
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)