目录
车牌号输入组件
密码支付键盘
如图
基于微信小程序组件封装,输出值为当前选择车牌号,可回显车牌号。
支持7位8位车牌号,因为我的项目没有此需求,所以没有测试,具体功能待验证。
话不多说,上代码。
json文件
{ "component": true, "usingComponents": { "van-overlay": "@vant/weapp/overlay/index", "van-divider": "@vant/weapp/divider/index" } }
wxs文件
Component({ /** * 组件的属性列表 */ properties: { // 组件显示 keyboardShow: { type: Boolean, value: false }, // 初始传入车牌号 vehicleNo: { type: String, value: '' }, // 车牌号位数 plateLimit: { type: Number, value: 7 } }, /** * 组件的初始数据 */ data: { keyboardShow: false, // 整体键盘显示 numberIsDis: 1, // 输入键盘不可点击 2可点击 fieldBoardShow: true, // 省键盘 provincesKeyList: '京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新', numberKeyList: '0123456789', englishKeyOneList: 'ABCDEFGHJKLMNPQRSTUV', englishKeyTwoList: 'WXYZ', currentFocus: 0, currIndex: 0, codeList: [], codeReset: [] }, /** * 组件的生命周期 * ready方法要正确执行需要在父页面中写入当前组件时,wx:if 绑定组件显示属性 * 组件隐藏之后要注销,否则ready方法只执行一次 */ ready: function() { let temp = [] let reset = [] let carLen = this.properties.vehicleNo ? this.properties.vehicleNo.length + 1 : 0 if (carLen) { let arr = this.properties.vehicleNo.split('') arr.forEach(item => { temp.push({ value: item }) reset.push({ value: '' }) }) // 解决车牌号异常数据导致的样式问题(车牌号位数不够) if (carLen < this.data.plateLimit) { let num = this.data.plateLimit - carLen for (let index = 0; index <= num; index++) { temp.push({ value: '' }) reset.push({ value: '' }) } } } else { // 初始化设置数据 for (let index = 0; index < this.data.plateLimit; index++) { temp.push({ value: '' }) reset.push({ value: '' }) } } this.setData({ codeList: temp, codeReset: reset, numberIsDis: carLen ? 2 : 1, fieldBoardShow: carLen ? false : true, currentFocus: carLen, currIndex: this.properties.vehicleNo ? this.properties.vehicleNo.length : 0 }) }, /** * 组件的方法列表 */ methods: { // 省份键盘 provinceKeyClick(e) { const { val } = e.currentTarget.dataset const { currentFocus, codeList } = this.data let temp = codeList temp[0].value = val this.setData({ codeList: temp, fieldBoardShow: false, currIndex: 1, numberIsDis: 1, currentFocus: currentFocus + 1 }) }, //数字键盘不可点击事件 numberKeyDisabled(e) { // 获取组件 // this.keyboard = this.selectComponent("#keyboard"); return }, // 数字键盘可点击 numberKeyEnabled(e) { const { currIndex, codeList } = this.data if (currIndex > codeList.length - 1) return const { val } = e.currentTarget.dataset let temp = this.data.codeList temp[currIndex].value = val this.setData({ codeList: temp, currIndex: currIndex + 1, currentFocus: currIndex + 1 }) }, // 字母键盘点击 englishKeyClick(e) { const { currIndex, codeList } = this.data if (currIndex > codeList.length - 1) return const { val } = e.currentTarget.dataset let temp = this.data.codeList temp[currIndex].value = val this.setData({ codeList: temp, currentFocus: currIndex + 1, currIndex: currIndex + 1, numberIsDis: 2 }) }, // 退格 backspace: function(e) { const { currIndex } = this.data let temp = this.data.codeList if (!currIndex) return temp[currIndex - 1].value = '' this.setData({ codeList: temp, currentFocus: currIndex - 1, currIndex: currIndex - 1, fieldBoardShow: currIndex === 1, numberIsDis: currIndex === 2 ? 1 : 2 }) }, // 关闭 closeKeyBoard: function(e) { const { codeReset } = this.data this.setData({ keyboardShow: false, codeList: codeReset, currentFocus: 0, currIndex: 0, fieldBoardShow: true, numberIsDis: 1 }) this.triggerEvent('closeKeyBoard') }, // 确定 confirmKeyBoard: function(e) { const { currIndex, codeList } = this.data if (currIndex < codeList.length) return let plate = '' codeList.map(item => (plate += item.value)) this.triggerEvent('keyboardConfirm', plate) this.closeKeyBoard() } } })
wxml文件
<!--车牌号输入组件--> <van-overlay show="{{ keyboardShow }}" z-index="9990"> <view class="keyBoard_content"> <!-- header --> <view class="top-part flex"> <view class="font-30 close" bindtap="closeKeyBoard">x</view> <view class="message color-333">输入车牌号</view> <view class="font-30 confirm {{currIndex === codeList.length ? 'confirm-active' : ''}}" bindtap="confirmKeyBoard">确定</view> </view> <!-- input --> <view class="license flex"> <view wx:for="{{codeList}}" wx:key="index" class="edit-text {{currentFocus === index ? 'border-active' : ''}} {{index === 2 ? 'space-left' : ''}}"> <view>{{item.value}}</view> </view> </view> <!-- 键盘 --> <view class="keyboard"> <!-- 省份键盘 --> <block wx:if="{{fieldBoardShow}}"> <view class="province-keyboard flex"> <view class="td td-nor color-333" wx:for="{{provincesKeyList}}" wx:key="index" wx:for-index="idx" wx:for-item="itemName" catch:tap="provinceKeyClick" data-index="{{idx}}" data-val="{{itemName}}" hover-class="board-active" hover-start-time="0" hover-stay-time="80" > {{itemName}} </view> </view> </block> <!--数字键盘--> <block wx:if="{{!fieldBoardShow}}"> <view class="number-keyboard flex between"> <!-- 不可点击 --> <block wx:if="{{numberIsDis === 1}}"> <view class="td td-num color-333 board-active" wx:for="{{numberKeyList}}" wx:key="idx" wx:for-index="idx" wx:for-item="itemName" catch:tap="numberKeyDisabled" data-val="{{itemName}}" > {{itemName}} </view> </block> <!-- 可点击 --> <block wx:if="{{numberIsDis === 2}}"> <view class="td td-num color-333" wx:for="{{numberKeyList}}" wx:key="idx" wx:for-index="idx" wx:for-item="itemName" catch:tap="numberKeyEnabled" data-index="{{idx}}" data-val="{{itemName}}" hover-class="board-active" hover-start-time="0" hover-stay-time="80" > {{itemName}} </view> </block> </view> </block> <!--字母键盘--> <block wx:if="{{!fieldBoardShow}}"> <view class="english-keyboard flex between"> <view class="td td-num color-333" wx:for="{{englishKeyOneList}}" wx:key="idx" wx:for-index="idx" wx:for-item="itemName" data-index="{{idx}}" data-val="{{itemName}}" hover-class="board-active" hover-start-time="0" hover-stay-time="80" catch:tap="englishKeyClick" > {{itemName}} </view> </view> <view class="english-keyboard flex englishtTwo"> <view class="td td-num color-333" wx:for="{{englishKeyTwoList}}" wx:key="idx" wx:for-index="idx" wx:for-item="itemName" data-index="{{idx}}" data-val="{{itemName}}" hover-class="board-active" hover-start-time="0" hover-stay-time="80" catch:tap="englishKeyClick" > {{itemName}} </view> </view> </block> <!--清除按钮--> <view catch:tap="backspace" class="delete flex" hover-class="board-active" hover-start-time="0" hover-stay-time="80" > <image class="deleteImg" src="/images/clear.png" /> </view> </view> </view> </van-overlay>
wxss文件
@import "../../styles/style.wxss"; .keyBoard_content { z-index: 9999; position: fixed; bottom: 0; left: 0; width: 100%; height: auto; background: #fff; } .top-part { width: 100%; padding: 25rpx 40rpx; height: 92rpx; justify-content: center; align-items: center; box-sizing: border-box; border-bottom: 1rpx solid #EAEAEA; margin-bottom: 15rpx; text-align: center; } .close { width: 10%; font-size: 47rpx; color: #A0A0A0; } .message { width: 80%; text-align: center; font-weight: Semibold; } .confirm { width: 10%; color: #A0A0A0; font-weight: Regular; } .confirm-active { color: #27B57D; } .license { box-sizing: border-box; justify-content: space-around; margin: 60rpx 90rpx 50rpx; } .edit-text { height: 80rpx; line-height: 80rpx; width: 60rpx; border: 1rpx solid #A0A0A0; border-radius: 8rpx; text-align: center; font-size: 36rpx; } .space-left { margin-left: 30rpx; } .border-active { border: 1rpx solid #5BCA92; } .keyboard { width: 100%; height: 450rpx; box-sizing: border-box; position: relative; } .province-keyboard { margin: 0 50rpx; flex-wrap: wrap; } .number-keyboard { margin: 0 5rpx; } .english-keyboard { margin: 0 5rpx; flex-wrap: wrap; } .englishtTwo { margin-left: 10%; } .td { font-family: "PingFangSC"; font-size: 36rpx; font-weight: Medium; margin: 12rpx 4rpx; border: 1rpx solid #E0E0E0; border-radius: 8rpx; height: 84rpx; line-height: 84rpx; text-align: center; } .td-nor { flex: 0 1 9%; } .td-num { flex: 0 1 8%; } .board-active { box-shadow: 0 0 0 #e5e5e5; background: #e5e5e5; } .delete { width: 140rpx; height: 84rpx; text-align: center; background-color: #D8D8D8; border-radius: 8rpx; position: absolute; right: 80rpx; bottom: 30rpx; justify-content: center; align-items: center; } .deleteImg { width: 44rpx; height: 30rpx; }
style.wxss 文件
.van-dialog__header { padding-bottom: 20rpx; } .flex { display: flex; } .between { justify-content: space-between; } .font-30 { font-size: 30rpx; } .color-333 { color: #333333; }
交互样式如上图
上代码:
json文件
{ "component": true, "usingComponents": { "van-popup": "@vant/weapp/popup/index", "van-tab": "/miniprogram_npm/@vant/weapp/tab/index" } }
wxs文件
import { throttle } from '../../utils/throttle' const passwordInputData = ['', '', '', '', '', ''] Component({ /** * 组件的属性列表 */ properties: { // 显示隐藏弹窗 passWordShow: { type: Boolean, observer(value) { if (!value) { this.setData({ passwordInput: JSON.parse(JSON.stringify(passwordInputData)), passwordIndex: -1 }) } } }, // 支付金额 payAmount: { type: Number } }, /** * 组件的初始数据 */ data: { passwordInput: JSON.parse(JSON.stringify(passwordInputData)), passwordIndex: -1, keyboardNumber: '123456789*0*', password: '' }, /** * 启用插槽 */ options: {}, lifetimes: { attached: function() {} }, externalClasses: ['custom-class'], /** * 组件的方法列表 */ methods: { // 忘记密码 forgetPassWord() { this.onClose() wx.navigateTo({ url: `/pages/manage-password/refund-password/index?source=Back` }) }, //tab切换 onTabChange(e) { this.triggerEvent('onTabChange', { currStatus: e.currentTarget.dataset.value }) }, onClose() { this.setData({ passwordInput: JSON.parse(JSON.stringify(passwordInputData)), passWordShow: false }) this.triggerEvent('closeFun') }, // throttle防抖 tapKeyboard: throttle(function(e) { const { val } = e.currentTarget.dataset const passwordIndex = this.data.passwordIndex + 1 if (passwordIndex > 5) { return } this.data.passwordInput[passwordIndex] = val this.setData({ passwordIndex, passwordInput: this.data.passwordInput }) if (passwordIndex === 5) { const password = this.data.passwordInput.join('') this.triggerEvent('submitFun', { password: password }) this.onClose() } }), tapKeyboardDelete() { const passwordIndex = this.data.passwordIndex - 1 if (passwordIndex < -1) { return } this.data.passwordInput[this.data.passwordIndex] = '' this.setData({ passwordIndex, passwordInput: this.data.passwordInput }) } } })
// throttle export function throttle(fn, delay) { let timer = null return function(...args) { clearTimeout(timer) timer = setTimeout(() => fn.apply(this, [...args]), delay) } }
wxml文件
<van-popup show="{{ passWordShow }}" closeable close-icon-position="top-left" position="bottom" close-icon="cross" custom-style="height: 20%" bind:close="onClose" z-index="99" custom-style="height: 914rpx" > <view class="content"> <view class="title color-333">请输入退款密码</view> <view class="password-box"> <view class="password-main"> <view class="password-item" wx:for="{{passwordInput}}" wx:for-index="boxIndex" wx:key='boxIndex' > <view class="star">{{item ? "*" : ''}}</view> </view> </view> <view class="forget" catch:tap="forgetPassWord">忘记密码</view> </view> <view class="keyboard flex between"> <!-- 数字键盘可点击 --> <view class="td flex color-333" wx:for="{{keyboardNumber}}" wx:key="index" wx:for-index="idx" wx:for-item="itemName" data-index="{{idx}}" data-val="{{itemName}}" hover-class="board_bg" hover-start-time="0" hover-stay-time="80" > <view class="del_icon flex" wx:if="{{idx === 11}}" catch:tap="tapKeyboardDelete" data-index="{{idx}}" data-val="{{itemName}}" > <image class="deleteImg" src="/images/clear.png" /> </view> <view class="keyboard-num flex" wx:if="{{idx !== 9 && idx !== 11}}" catch:tap="tapKeyboard" data-index="{{idx}}" data-val="{{itemName}}" > {{itemName}} </view> </view> </view> </view> </van-popup>
wxss文件
style.wxss文件上面有
@import "../../styles/style.wxss"; .title{ font-size: 34rpx; font-family: PingFangSC, PingFangSC-Medium; font-weight: Medium; text-align: center; min-height: 136rpx; line-height: 136rpx; border-bottom: 1px solid #eaeaea; } .van-popup__close-icon--top-left { top: 50rpx!important; } .password-box{ padding-top: 40rpx; } .forget{ font-size: 28rpx; text-align: right; color: #0091ff; padding: 12rpx 28rpx 20rpx; } .password-main{ width: 684rpx; height: 104rpx; border: 1px solid #a1a1a1; border-radius: 3px; display: flex; margin: 0 auto; } .password-item{ width: 114rpx; border-right: 1px solid #a1a1a1; display: flex; justify-content: center; align-items: center; } .password-item:last-child{ border: none; } .star{ font-size: 60rpx; line-height: 108rpx; padding-top: 20rpx; } .keyboard{ width: 100%; height: 490rpx; padding: 40rpx 16rpx 0; box-sizing: border-box; background: #EEEEEE; flex-wrap: wrap; } .td { flex: 0 1 32%; border-radius: 8rpx; background-color: #fff; font-size: 50rpx; font-weight: Regular; align-items: center; justify-content: center; margin-bottom: 16rpx; height: 96rpx; } .board_bg { box-shadow: 0 0 0 #e5e5e5; background: #e5e5e5; } .del_icon { width: 100%; height: 100%; align-items: center; justify-content: center; } .del_icon .deleteImg { width: 54rpx; height: 34rpx; } .keyboard-num { width: 100%; height: 100%; justify-content: center; align-items: center; }