目录
车牌号输入组件
如图
基于微信小程序组件封装,输出值为当前选择车牌号,可回显车牌号。
支持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;
}