微信小程序中實現(xiàn)車牌輸入功能
前言
哈哈哈,上新文章啦。好久沒有更新啦,今天乘著休息來總結(jié)下之前用的到自定義鍵盤來輸入車輛號牌微信組件。下面是效果圖,請欣賞:

背景
近期做了一個和車有關(guān)的項目,有車肯定就有車牌,我們都知道車牌是有一定規(guī)律的,如果簡單的給個輸入框的話。。。。。。這里省略一萬字哈,從小我的編程老師告訴我不要相信任何用戶輸入的東西。嗯嗯!現(xiàn)在想想還真的是這樣,總有一些別具一格的用戶就喜歡反著來,也不知道是真不懂還是搞破壞哈。還有個老師告訴我永遠(yuǎn)要把用戶當(dāng)SB,雖然自己也是用戶,感覺不好,但是話糙理不糙啊,因為你永遠(yuǎn)不知道使用你寫的東西的是什么。。。。。(甚至是不是人)。在這樣的背景下你說要讓用戶輸入一個正確的車牌號,那可真是比登天還難啊,太南了,臣妾做不到啊。
大猜想
既然這樣哈,我們自己也來當(dāng)一回用戶看看大概有什么情況發(fā)生哈,來咯,不要走開哦,下面就是發(fā)揮用戶腦洞的時候了。
- 我a.12345
- 鄂a.ii111
- Xa.6666666
- za.哈哈哈哈哈
- 。。。。。。
哇哦,估計寫一天都寫不完呢,后面看大家的啦,這里有一個前提就是咱不考慮以英文開頭的車牌,如果需要考慮大家可以舉一反三啦。
找規(guī)律
其實沒啥規(guī)律可找的,直接上百度一搜就知道車牌的規(guī)則。前面是省份簡稱,第二位是字母,后面是字母和數(shù)字的混合,這里有幾個特殊的就是教練車、港澳車進(jìn)大陸、領(lǐng)事館的車。另外字母和字母o和數(shù)字1和0不好辨認(rèn),所以字母i和字母o去掉了,最后規(guī)律就有了。
結(jié)構(gòu)和樣式
知道規(guī)律后就可以開始動手操作了,先看看設(shè)計圖的鍵盤布局:

上面圖片是省份簡稱鍵盤布局

上面圖片是第二位字母鍵盤布局

上面圖片是后面幾位的鍵盤布局
下面就根據(jù)這幾個布局來寫結(jié)構(gòu)了:
<view class="keyboard" wx:if="{{isShow}}">
<view class="item">
<view wx:for="{{dataArr1}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="item">
<view wx:for="{{dataArr2}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="item">
<view wx:for="{{dataArr3}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="item" wx:if="{{dataArr4.length}}">
<view wx:for="{{dataArr4}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="delbtn" bindtap="delKey" wx:if="{{keyType == 'carlicense'}}"><image src="./icon_del.png"></image></view>
</view>
<view class="mask" bindtap="hideKeyBoard" wx:if="{{isShow}}"></view>
分別把數(shù)據(jù)放入四個數(shù)組中,由于第二位少了一些,所以干脆少一行,還有刪除的按鈕,以及最后的遮罩層,用于點擊其他地方關(guān)閉鍵盤
接下來先加幾個測試的數(shù)據(jù)把基本的顏色寫好:
data: {
dataArr1:["京","滬","粵","津","冀","晉","遼","蒙","黑","吉"],
dataArr2:["蘇","浙","皖","閩","贛","魯","豫","鄂","湘"],
dataArr3:["川","貴","云","渝","桂","瓊","藏","陜"],
dataArr4:["甘","青","寧","新","臺"]
}
這里以輸入省份的為例
接下來就是把我們的樣式添加上去就可以看到效果了:
.keyboard {
position: fixed;
left: 0;
bottom: 0;
z-index: 99999;
width: 100%;
background: #d1d6d9;
padding: 20rpx 10rpx 0;
padding-bottom:calc(30px + env(safe-area-inset-bottom)/2);
box-sizing: border-box;
}
.keyboard .item {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
}
.keyboard .item view {
width: 9%;
height: 70rpx;
line-height: 70rpx;
text-align: center;
margin-right: 10rpx;
background: #ffffff;
border-radius: 10rpx;
font-size: 28rpx;
}
.keyboard .item view:last-child {
margin-right: 0;
}
.keyboard .delbtn {
position: fixed;
right: 10rpx;
bottom: calc(40px + env(safe-area-inset-bottom)/2);
height: 70rpx;
width: 18%;
z-index: 999999;
background: #adb3bd;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
}
.keyboard .delbtn image{
width: 60rpx;
height: 60rpx;
}
.mask{
position: fixed;
left: 0;
top: 113rpx;
bottom: 0;
right: 0;
z-index: 99998;
}
這里樣式就不多說了,大家可以按照自己的喜好來就行
現(xiàn)在已經(jīng)可以看到效果了,如圖:

組件實現(xiàn)
組件的實現(xiàn)其實很簡單,主要需要知道微信組件的用法就ok。
參數(shù)
實現(xiàn)之前來看看需要什么參數(shù),由于是鍵盤肯定是需要顯示和隱藏的,所以需要一個顯示和隱藏的參數(shù)這里就命名為isShow。再看我們的樣式如果是輸入第二位或者后面的呢是不是之前定義的幾個數(shù)組數(shù)據(jù)就得改變,問題來了什么時候改變呢?是不是應(yīng)該在點擊輸入的地方就打開這個時候就知道了是輸入省份還是輸入第二位還是后面的,所以這里需要有一個參數(shù)來表示當(dāng)前是需要顯示什么類型的鍵盤暫命名為keyType。到這里參數(shù)有了,再來看看是否需要設(shè)置默認(rèn)值是啥,對于isShow來說開始肯定是false即為不顯示的,至于keyType默認(rèn)那個都行,這里默認(rèn)值設(shè)為省份的。這里的參數(shù)其實就是需要調(diào)用組件時傳遞過來的參數(shù),所以這兩個參數(shù)就是設(shè)為組件的屬性。
有了上面的分析,組件的大概就出來了,代碼如下:
Component({
properties: {
keyType:{
type:String,
value:'province'
},
isShow:{
type:Boolean,
value:false
}
},
data: {
dataArr1:["京","滬","粵","津","冀","晉","遼","蒙","黑","吉"],
dataArr2:["蘇","浙","皖","閩","贛","魯","豫","鄂","湘"],
dataArr3:["川","貴","云","渝","桂","瓊","藏","陜"],
dataArr4:["甘","青","寧","新","臺"]
}
})
鍵盤類型的判斷
ok,上面已經(jīng)把鍵盤所需參數(shù)考慮好了,接下來就是需要根據(jù)傳入的keyType來切換不同的鍵盤數(shù)組的值了。其實就是在組件方法里面寫一個方法來切換就行了,實現(xiàn)如下:
Component({
properties: {
keyType:{
type:String,
value:'province'
},
isShow:{
type:Boolean,
value:false
}
},
data: {
dataArr1:[],
dataArr2:[],
dataArr3:[],
dataArr4:[]
},
methods: {
changeType(){
if(this.data.keyType == 'letter'){
this.setData({
dataArr1:["Q","W","E","R","T","Y","U","P","N","M"],
dataArr2:["A","S","D","F","G","H","J","K","L"],
dataArr3:["Z","X","C","V","B"],
dataArr4:[]
})
}else if(this.data.keyType == 'province'){
this.setData({
dataArr1:["京","滬","粵","津","冀","晉","遼","蒙","黑","吉"],
dataArr2:["蘇","浙","皖","閩","贛","魯","豫","鄂","湘"],
dataArr3:["川","貴","云","渝","桂","瓊","藏","陜"],
dataArr4:["甘","青","寧","新","臺"]
})
}else if(this.data.keyType == 'carlicense'){
this.setData({
dataArr1:["1","2","3","4","5","6","7","8","9","0"],
dataArr2:["A","B","C","D","E","F","G","H","J","K"],
dataArr3:["L","M","N","P","Q","R","S","T","U","V"],
dataArr4:["W","X","Y","Z","港","澳","學(xué)","領(lǐng)"]
})
}
}
}
})
切的方法有了,現(xiàn)在就是在初始化的時候調(diào)用這個方法就行了,修改代碼如下:
Component({
properties: {
keyType:{
type:String,
value:'province'
},
isShow:{
type:Boolean,
value:false
}
},
data: {
dataArr1:[],
dataArr2:[],
dataArr3:[],
dataArr4:[]
},
attached(){
this.changeType()
},
methods: {
changeType(){
if(this.data.keyType == 'letter'){
this.setData({
dataArr1:["Q","W","E","R","T","Y","U","P","N","M"],
dataArr2:["A","S","D","F","G","H","J","K","L"],
dataArr3:["Z","X","C","V","B"],
dataArr4:[]
})
}else if(this.data.keyType == 'province'){
this.setData({
dataArr1:["京","滬","粵","津","冀","晉","遼","蒙","黑","吉"],
dataArr2:["蘇","浙","皖","閩","贛","魯","豫","鄂","湘"],
dataArr3:["川","貴","云","渝","桂","瓊","藏","陜"],
dataArr4:["甘","青","寧","新","臺"]
})
}else if(this.data.keyType == 'carlicense'){
this.setData({
dataArr1:["1","2","3","4","5","6","7","8","9","0"],
dataArr2:["A","B","C","D","E","F","G","H","J","K"],
dataArr3:["L","M","N","P","Q","R","S","T","U","V"],
dataArr4:["W","X","Y","Z","港","澳","學(xué)","領(lǐng)"]
})
}
}
}
})
到這里組件的基本功能已經(jīng)完成了,但是當(dāng)我們點擊鍵盤上的內(nèi)容的時候,你會發(fā)現(xiàn)沒有反應(yīng),嗯嗯。。。。。這里好像漏了一個東西,既然是鍵盤肯定是需要得到輸入結(jié)果的啦。
獲取輸入內(nèi)容
要獲取鍵盤輸入的內(nèi)容就需要給鍵盤的每個按鍵新增事件來獲取輸入內(nèi)容,將之前的結(jié)構(gòu)中新增事件,具體可參見文章第一段代碼,具體的實現(xiàn)代碼如下:
methods: {
inputKey(e){
console.log(e.currentTarget.dataset.value)
},
delKey(e){
console.log(e.currentTarget.dataset.value)
},
hideKeyBoard(){
this.setData({
isShow:false
})
}
}
這里將刪除和關(guān)閉鍵盤的時間也添加上了,通過以上兩個方法就能獲取輸入的值了。這時當(dāng)我們點擊某個字符時就會看到控制面板里打印出剛剛選擇的值了。

可是我需要不是打印出值啊,是需要將值顯示在頁面上才行,這里就需要將組建獲取到的值傳遞給調(diào)用改組件的頁面了,如何傳遞給調(diào)用該組件的頁面呢?
組件傳參
這里咱們就可以去微信小程序的官方文檔看看了,畢竟官方文檔是個好東西嘛,找到下圖所示的地方:

我們這里用到的就是組件通信的第二點事件,可以傳遞任意數(shù)據(jù)的,那么根據(jù)官方文檔的介紹我相信大家一看就知道怎么使用了,代碼如下:
methods: {
inputKey(e){
this.triggerEvent('inputword', {type:'input',value:e.currentTarget.dataset.value})
},
delKey(e){
this.triggerEvent('inputword', {type:'del'})
},
hideKeyBoard(){
this.setData({
isShow:false
})
this.triggerEvent('inputword', {type:'blur'})
}
}
這里呢是將所以的操作都通過一個事件來傳遞數(shù)據(jù),通過增加一個type來區(qū)分到底是輸入、刪除還是關(guān)閉鍵盤。
組件使用
嗯嗯,不容易啊,終于到了使用組件的時候了,這里根據(jù)微信組件的用法如下操作:
在頁面配置文件中引入組件地址
在頁面中添加組件的標(biāo)簽
在添加的標(biāo)簽上面添加需要傳遞的參數(shù)和事件
相關(guān)代碼如下:
{
"navigationBarTitleText": "新增車輛",
"usingComponents": {
"keyboard":"../../components/keyboard/index"
}
}
在需要用到改組件的頁面的配置文件中加入上面帶代碼
<view class="bind-car">
<view class="car-province {{focusProvince?'active':''}}">
<view bindtap="chooseProvinceCn">{{provinceCn}}</view>
<view bindtap="chooseProvinceCode">{{provinceCode}}</view>
</view>
<view class="car-number {{focusCode?'active':''}}" bindtap="chooseCarCode">{{carCode}}</view>
</view>
<keyboard bindinputword="inputWord" keyType="{{setKeyType}}" isShow="{{showKeyBoard}}"></keyboard>
在使用到的頁面中加入上面最后一行的代碼,并添加上相信的參數(shù)和事件
下一步就是在頁面的js中來處理相應(yīng)的參數(shù)和事件,具體代碼如下:
Page({
data: {
focusProvince:false,
focusCode:false,
setKeyType:'province',
showKeyBoard:false,
keyIndex:0,
provinceCn:'',
provinceCode:'',
carCode:''
},
inputWord(e){
if(e.detail.type == 'input'){
if(this.data.keyIndex == 0){
this.setData({
provinceCn:e.detail.value
})
}else if(this.data.keyIndex == 1){
this.setData({
provinceCode:e.detail.value
})
}else if(this.data.keyIndex == 2){
if(this.data.carCode.length < 6){
this.setData({
carCode:this.data.carCode + e.detail.value
})
}
}
}else if(e.detail.type == 'del'){
if(this.data.carCode){
this.setData({
carCode:this.data.carCode.substr(0, this.data.carCode.length - 1)
})
}
}else if(e.detail.type == 'blur'){
this.setData({
focusCode:false,
focusProvince:false
})
}
},
chooseProvinceCn(){
this.setData({
setKeyType:'province',
showKeyBoard:true,
keyIndex:0,
focusProvince:true,
focusCode:false
})
},
chooseProvinceCode(){
this.setData({
setKeyType:'letter',
showKeyBoard:true,
keyIndex:1,
focusProvince:true,
focusCode:false
})
},
chooseCarCode(){
this.setData({
setKeyType:'carlicense',
showKeyBoard:true,
keyIndex:2,
focusCode:true,
focusProvince:false
})
}
})
頁面中的inputWord就是我們最終需要處理的事件,另外幾個是輸入后控制焦點并顯示相應(yīng)的紅色方框的開關(guān)
測試
這一步就是程序小哥哥小姐姐比較害怕的,測試的小哥哥小姐姐就那咋自己寫的代碼不停的亂搞一通,哈哈哈,最后骨頭里挑刺。這里呢當(dāng)我們分別選擇不同輸入的type時會發(fā)現(xiàn)鍵盤的內(nèi)容沒有改變,嗯嗯,原來還是寫了個bug給自己啊。
解決鍵盤類型判斷的bug
通過上面自己簡單的測試后發(fā)現(xiàn)有個bug需要去修復(fù),其實這個問題的點在于每次去顯示鍵盤時傳遞給組件的keyType有緩存導(dǎo)致的,所以需要再組件中屬性聲明的地方來個監(jiān)聽變化咯,說干就干,改好了馬上下班,代碼如下:
Component({
properties: {
keyType:{
type:String,
value:'letter',
observer:function(newVal,oldVal){
this.changeType()
}
},
isShow:{
type:Boolean,
value:false
}
}
})
在屬性中新增observer的監(jiān)聽函數(shù),當(dāng)有變化的時候就去調(diào)用判斷類型的函數(shù)就可以了。這樣就可以愉快的使用。最后打卡,背包走人咯。。。。等等后面還有呢
結(jié)束語
目前這個組件也只是為了完成需求而寫的,可能實際使用過程中還是會有很多問題的,歡迎大家提出哦。最后放上每個文件完整的代碼哦
組件的代碼
WXML
<view class="keyboard" wx:if="{{isShow}}">
<view class="item">
<view wx:for="{{dataArr1}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="item">
<view wx:for="{{dataArr2}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="item">
<view wx:for="{{dataArr3}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="item" wx:if="{{dataArr4.length}}">
<view wx:for="{{dataArr4}}" wx:key="unique" bindtap="inputKey" data-value="{{item}}">{{item}}</view>
</view>
<view class="delbtn" bindtap="delKey" wx:if="{{keyType == 'carlicense'}}"><image src="./icon_del.png"></image></view>
</view>
<view class="mask" bindtap="hideKeyBoard" wx:if="{{isShow}}"></view>
WXSS
.keyboard {
position: fixed;
left: 0;
bottom: 0;
z-index: 99999;
width: 100%;
background: #d1d6d9;
padding: 20rpx 10rpx 0;
padding-bottom:calc(30px + env(safe-area-inset-bottom)/2);
box-sizing: border-box;
}
.keyboard .item {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
}
.keyboard .item view {
width: 9%;
height: 70rpx;
line-height: 70rpx;
text-align: center;
margin-right: 10rpx;
background: #ffffff;
border-radius: 10rpx;
font-size: 28rpx;
}
.keyboard .item view:last-child {
margin-right: 0;
}
.keyboard .delbtn {
position: fixed;
right: 10rpx;
bottom: calc(40px + env(safe-area-inset-bottom)/2);
height: 70rpx;
width: 18%;
z-index: 999999;
background: #adb3bd;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
}
.keyboard .delbtn image{
width: 60rpx;
height: 60rpx;
}
.mask{
position: fixed;
left: 0;
top: 113rpx;
bottom: 0;
right: 0;
z-index: 99998;
}
JS
Component({
properties: {
keyType:{
type:String,
value:'letter',
observer:function(newVal,oldVal){
this.changeType()
}
},
isShow:{
type:Boolean,
value:false
}
},
data: {
dataArr1:[],
dataArr2:[],
dataArr3:[],
dataArr4:[]
},
attached(){
this.changeType()
},
methods: {
changeType(){
if(this.data.keyType == 'letter'){
this.setData({
dataArr1:["Q","W","E","R","T","Y","U","P","N","M"],
dataArr2:["A","S","D","F","G","H","J","K","L"],
dataArr3:["Z","X","C","V","B"],
dataArr4:[]
})
}else if(this.data.keyType == 'province'){
this.setData({
dataArr1:["京","滬","粵","津","冀","晉","遼","蒙","黑","吉"],
dataArr2:["蘇","浙","皖","閩","贛","魯","豫","鄂","湘"],
dataArr3:["川","貴","云","渝","桂","瓊","藏","陜"],
dataArr4:["甘","青","寧","新","臺"]
})
}else if(this.data.keyType == 'carlicense'){
this.setData({
dataArr1:["1","2","3","4","5","6","7","8","9","0"],
dataArr2:["A","B","C","D","E","F","G","H","J","K"],
dataArr3:["L","M","N","P","Q","R","S","T","U","V"],
dataArr4:["W","X","Y","Z","港","澳","學(xué)","領(lǐng)"]
})
}
},
inputKey(e){
this.triggerEvent('inputword', {type:'input',value:e.currentTarget.dataset.value})
},
delKey(e){
this.triggerEvent('inputword', {type:'del'})
},
hideKeyBoard(){
this.setData({
isShow:false
})
this.triggerEvent('inputword', {type:'blur'})
}
}
})
使用頁面代碼
JSON
{
"navigationBarTitleText": "新增車輛",
"usingComponents": {
"keyboard":"../../components/keyboard/index"
}
}
WXML
<view class="bind-car">
<view class="car-province {{focusProvince?'active':''}}">
<view bindtap="chooseProvinceCn">{{provinceCn}}</view>
<view bindtap="chooseProvinceCode">{{provinceCode}}</view>
</view>
<view class="car-number {{focusCode?'active':''}}" bindtap="chooseCarCode">{{carCode}}</view>
</view>
<keyboard bindinputword="inputWord" keyType="{{setKeyType}}" isShow="{{showKeyBoard}}"></keyboard>
WXSS
.bind-car {
display: flex;
align-items: center;
background: #FFFFFF;
padding: 25rpx 30rpx;
}
.bind-car .car-province {
margin-right: 30rpx;
width: 170rpx;
height: 88rpx;
border: 1rpx solid #999999;
border-radius: 4rpx;
display: flex;
}
.bind-car .car-province view {
width: 86rpx;
height: 88rpx;
line-height: 88rpx;
text-align: center;
font-size: 34rpx;
font-weight: 500;
color: #333333;
}
.bind-car .car-province view:first-child {
position: relative;
}
.bind-car .car-province view:first-child::after {
content: '';
position: absolute;
right: 0;
top: 50%;
width: 1rpx;
height: 40rpx;
background: #999999;
margin-top: -20rpx;
}
.bind-car .car-province.active {
border-color: #FF5152;
}
.bind-car .car-province.active view:first-child::after {
background: #E83333;
}
.car-number {
width: 100%;
height: 88rpx;
line-height: 88rpx;
border: 1rpx solid #999999;
border-radius: 4rpx;
font-size: 34rpx;
font-weight: 500;
color: #333333;
text-align: center;
}
.car-number.active {
border-color: #E83333;
}
JS
Page({
data: {
focusProvince:false,
focusCode:false,
setKeyType:'province',
showKeyBoard:false,
keyIndex:0,
provinceCn:'',
provinceCode:'',
carCode:''
},
inputWord(e){
if(e.detail.type == 'input'){
if(this.data.keyIndex == 0){
this.setData({
provinceCn:e.detail.value
})
}else if(this.data.keyIndex == 1){
this.setData({
provinceCode:e.detail.value
})
}else if(this.data.keyIndex == 2){
if(this.data.carCode.length < 6){
this.setData({
carCode:this.data.carCode + e.detail.value
})
}
}
}else if(e.detail.type == 'del'){
if(this.data.carCode){
this.setData({
carCode:this.data.carCode.substr(0, this.data.carCode.length - 1)
})
}
}else if(e.detail.type == 'blur'){
this.setData({
focusCode:false,
focusProvince:false
})
}
},
chooseProvinceCn(){
this.setData({
setKeyType:'province',
showKeyBoard:true,
keyIndex:0,
focusProvince:true,
focusCode:false
})
},
chooseProvinceCode(){
this.setData({
setKeyType:'letter',
showKeyBoard:true,
keyIndex:1,
focusProvince:true,
focusCode:false
})
},
chooseCarCode(){
this.setData({
setKeyType:'carlicense',
showKeyBoard:true,
keyIndex:2,
focusCode:true,
focusProvince:false
})
}
})
到此這篇關(guān)于微信小程序中實現(xiàn)車牌輸入功能的文章就介紹到這了,更多相關(guān)微信車牌輸入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)節(jié)點的刪除與序號重建實例
這篇文章主要介紹了JavaScript實現(xiàn)節(jié)點的刪除與序號重建方法,涉及javascript針對頁面節(jié)點的刪除與遍歷技巧,非常具有實用價值,需要的朋友可以參考下2015-08-08
JS實現(xiàn)圖片旋轉(zhuǎn)動畫效果封裝與使用示例
這篇文章主要介紹了JS實現(xiàn)圖片旋轉(zhuǎn)動畫效果封裝與使用,結(jié)合實例形式分析了JavaScript實現(xiàn)圖片元素旋轉(zhuǎn)的相關(guān)功能代碼的封裝與使用操作技巧,需要的朋友可以參考下2018-07-07
JavaScript中數(shù)組的22種方法必學(xué)(推薦)
這篇文章主要介紹了JavaScript中數(shù)組的22種方法必學(xué)(推薦)的相關(guān)資料,需要的朋友可以參考下2016-07-07

