微信小程式中實現車牌輸入功能
前言
哈哈哈,上新文章啦。好久沒有更新啦,今天乘著休息來總結下之前用的到自定義鍵盤來輸入車輛號牌微信元件。下面是效果圖,請欣賞:
背景
近期做了一個和車有關的專案,有車肯定就有車牌,我們都知道車牌是有一定規律的,如果簡單的給個輸入框的話。。。。。。這裡省略一萬字哈,從小我的程式設計老師告訴我不要相信任何使用者輸入的東西。嗯嗯!現在想想還真的是這樣,總有一些別具一格的使用者就喜歡反著來,也不知道是真不懂還是搞破壞哈。還有個老師告訴我永遠要把使用者當SB,雖然自己也是使用者,感覺不好,但是話糙理不糙啊,因為你永遠不知道使用你寫的東西的是什麼。。。。。(甚至是不是人)。在這樣的背景下你說要讓使用者輸入一個正確的車牌號,那可真是比登天還難啊,太南了,臣妾做不到啊。
大猜想
既然這樣哈,我們自己也來當一回使用者看看大概有什麼情況發生哈,來咯,不要走開哦,下面就是發揮使用者腦洞的時候了。
- 我a.12345
- 鄂a.ii111
- Xa.6666666
- za.哈哈哈哈哈
- 。。。。。。
哇哦,估計寫一天都寫不完呢,後面看大家的啦,這裡有一個前提就是咱不考慮以英文開頭的車牌,如果需要考慮大家可以舉一反三啦。
找規律
其實沒啥規律可找的,直接上百度一搜就知道車牌的規則。前面是省份簡稱,第二位是字母,後面是字母和數字的混合,這裡有幾個特殊的就是教練車、港澳車進大陸、領事館的車。另外字母和字母o和數字1和0不好辨認,所以字母i和字母o去掉了,最後規律就有了。
結構和樣式
知道規律後就可以開始動手操作了,先看看設計圖的鍵盤佈局:
上面圖片是省份簡稱鍵盤佈局
上面圖片是第二位字母鍵盤佈局
上面圖片是後面幾位的鍵盤佈局
下面就根據這幾個佈局來寫結構了:
<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>
分別把資料放入四個陣列中,由於第二位少了一些,所以乾脆少一行,還有刪除的按鈕,以及最後的遮罩層,用於點選其他地方關閉鍵盤
接下來先加幾個測試的資料把基本的顏色寫好:
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; }
這裡樣式就不多說了,大家可以按照自己的喜好來就行
現在已經可以看到效果了,如圖:
元件實現
元件的實現其實很簡單,主要需要知道微信元件的用法就ok。
引數
實現之前來看看需要什麼引數,由於是鍵盤肯定是需要顯示和隱藏的,所以需要一個顯示和隱藏的引數這裡就命名為isShow。再看我們的樣式如果是輸入第二位或者後面的呢是不是之前定義的幾個陣列資料就得改變,問題來了什麼時候改變呢?是不是應該在點選輸入的地方就開啟這個時候就知道了是輸入省份還是輸入第二位還是後面的,所以這裡需要有一個引數來表示當前是需要顯示什麼型別的鍵盤暫命名為keyType。到這裡引數有了,再來看看是否需要設定預設值是啥,對於isShow來說開始肯定是false即為不顯示的,至於keyType預設那個都行,這裡預設值設為省份的。這裡的引數其實就是需要呼叫元件時傳遞過來的引數,所以這兩個引數就是設為元件的屬性。
有了上面的分析,元件的大概就出來了,程式碼如下:
Component({ properties: { keyType:{ type:String,value:'province' },isShow:{ type:Boolean,value:false } },data: { dataArr1:["京","臺"] } })
鍵盤型別的判斷
ok,上面已經把鍵盤所需引數考慮好了,接下來就是需要根據傳入的keyType來切換不同的鍵盤陣列的值了。其實就是在元件方法裡面寫一個方法來切換就行了,實現如下:
Component({ properties: { keyType:{ type:String,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:["京","臺"] }) }else if(this.data.keyType == 'carlicense'){ this.setData({ dataArr1:["1","2","3","4","5","6","7","8","9","0"],"B","K"],dataArr3:["L","M","Q","V"],dataArr4:["W","Z","港","澳","學","領"] }) } } } })
切的方法有了,現在就是在初始化的時候呼叫這個方法就行了,修改程式碼如下:
Component({ properties: { keyType:{ type:String,attached(){ this.changeType() },"領"] }) } } } })
到這裡元件的基本功能已經完成了,但是當我們點選鍵盤上的內容的時候,你會發現沒有反應,嗯嗯。。。。。這裡好像漏了一個東西,既然是鍵盤肯定是需要得到輸入結果的啦。
獲取輸入內容
要獲取鍵盤輸入的內容就需要給鍵盤的每個按鍵新增事件來獲取輸入內容,將之前的結構中新增事件,具體可參見文章第一段程式碼,具體的實現程式碼如下:
methods: { inputKey(e){ console.log(e.currentTarget.dataset.value) },delKey(e){ console.log(e.currentTarget.dataset.value) },hideKeyBoard(){ this.setData({ isShow:false }) } }
這裡將刪除和關閉鍵盤的時間也新增上了,通過以上兩個方法就能獲取輸入的值了。這時當我們點選某個字元時就會看到控制面板裡打印出剛剛選擇的值了。
可是我需要不是打印出值啊,是需要將值顯示在頁面上才行,這裡就需要將組建獲取到的值傳遞給呼叫改元件的頁面了,如何傳遞給呼叫該元件的頁面呢?
元件傳參
這裡咱們就可以去微信小程式的官方文件看看了,畢竟官方文件是個好東西嘛,找到下圖所示的地方:
我們這裡用到的就是元件通訊的第二點事件,可以傳遞任意資料的,那麼根據官方文件的介紹我相信大家一看就知道怎麼使用了,程式碼如下:
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'}) } }
這裡呢是將所以的操作都通過一個事件來傳遞資料,通過增加一個type來區分到底是輸入、刪除還是關閉鍵盤。
元件使用
嗯嗯,不容易啊,終於到了使用元件的時候了,這裡根據微信元件的用法如下操作:
在頁面配置檔案中引入元件地址
在頁面中新增元件的標籤
在新增的標籤上面新增需要傳遞的引數和事件
相關程式碼如下:
{ "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>
在使用到的頁面中加入上面最後一行的程式碼,並新增上相信的引數和事件
下一步就是在頁面的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,focusProvince:true,focusCode:false }) },chooseProvinceCode(){ this.setData({ setKeyType:'letter',keyIndex:1,chooseCarCode(){ this.setData({ setKeyType:'carlicense',keyIndex:2,focusCode:true,focusProvince:false }) } })
頁面中的inputWord就是我們最終需要處理的事件,另外幾個是輸入後控制焦點並顯示相應的紅色方框的開關
測試
這一步就是程式小哥哥小姐姐比較害怕的,測試的小哥哥小姐姐就那咋自己寫的程式碼不停的亂搞一通,哈哈哈,最後骨頭裡挑刺。這裡呢當我們分別選擇不同輸入的type時會發現鍵盤的內容沒有改變,嗯嗯,原來還是寫了個bug給自己啊。
解決鍵盤型別判斷的bug
通過上面自己簡單的測試後發現有個bug需要去修復,其實這個問題的點在於每次去顯示鍵盤時傳遞給元件的keyType有快取導致的,所以需要再元件中屬性宣告的地方來個監聽變化咯,說幹就幹,改好了馬上下班,程式碼如下:
Component({ properties: { keyType:{ type:String,value:'letter',observer:function(newVal,oldVal){ this.changeType() } },isShow:{ type:Boolean,value:false } } })
在屬性中新增observer的監聽函式,當有變化的時候就去呼叫判斷型別的函式就可以了。這樣就可以愉快的使用。最後打卡,揹包走人咯。。。。等等後面還有呢
結束語
目前這個元件也只是為了完成需求而寫的,可能實際使用過程中還是會有很多問題的,歡迎大家提出哦。最後放上每個檔案完整的程式碼哦
元件的程式碼
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>
&lhttp://www.cppcns.comt;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,oldVal){
this.changeType()
}
},dataArr4:[]
})
}else if(this.data.keyType == 'province'){
this.setData({
aesnb dataArr1:["京","領"]
})
}
},inputKey(e){
this.triggerEvent('inputword',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,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',focusCode:false }) },chooseProvinceCode(){ this.setData({ setKeyType:'letter',chooseCarCode(){ this.setData({ setKeyType:'carlicense',focusProvince:false }) } })
到此這篇關於微信小程式中實現車牌輸入功能的文章就介紹到這了,更多相關微信車牌輸入內容請搜尋我們以前的文章或繼www.cppcns.com續瀏覽下面的相關文章希望大家以後多多支援我們!