uni-app 实现 车牌键盘
上篇实现了个uview组件的车牌键盘,今天来实现一个纯手写的,智能化的车牌键盘,先看个效果图
上代码,先实现个基本的样式
<view class="car_num-text">
<template v-for="(item,index) in brand">
<text v-if="item == '+'" :key='index'
class="car_num-license new_energy nowrap"
:class="{ 'new-active': isActive === index && index === brand.length - 1 }"
@click.capture="onBrandClick" :data-index='index'>新</text>
<template v-else-if="index == 2">
<text class="f60">·</text>
<text :key='index' class="car_num-license"
:class="{'active': isActive === index }"
@click.capture="onBrandClick"
:data-index='index'>{{item}}</text>
</template>
<text v-else :key='index' class="car_num-license"
:class="{'active': isActive === index, 'new-active':isActive === index && index === brand.length - 1 }"
@click.capture="onBrandClick" :data-index='index'>{{item}}</text>
</template>
</view>
然后是键盘的样式
<template v-if='show'>
<view class='keyboard' @click='handleClick'>
<!-- 省份 -->
<view class="keyboard-box" v-if="isShowProvinceSelect" @click.stop=''>
<view class="keyboard_head">
<text class="cancel" @click.stop='cancelHandler'> 取消</text>
<text @click.stop="submit">完成</text>
</view>
<view class="keyboard_box">
<text v-for="(item,index) in province" :key='index' @click.stop="provinceClick"
:data-item="item">{{item}}</text>
<view class="close" @click.stop="clearHandler">
<image src="/static/add_car_delete.png" mode="widthFix" style="width:60rpx;height:60rpx" />
</view>
</view>
</view>
<!-- 车牌 -->
<view class="keyboard-box" v-if="isShowBrandSelect" @click.stop=''>
<view class="keyboard_head">
<text class="cancel" @click.stop='cancelHandler'>取消</text>
<text @click.stop="submit">完成</text>
</view>
<view class="keyboard_box">
<text v-for="(item,index) in brand_code" :key='index' @click.stop="brandCodeHandler" :data-item="item"
:class="{'color1': !item.isShow }">{{ item.code }}</text>
<text @click.stop="clearHandler" class="delete">删除</text>
</view>
</view>
</view>
</template>
定义一些基础变量
props: {
value: { default: '', type: String },
},
data() {
return {
show: false,
isActive: 0,
brand: ['', '', '', '', '', '', '', '+'],
province: ['京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑', '湘', '皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘','晋', '蒙', '陕', '吉', '闽', '贵', '粤', '青', '藏', '川', '宁', '琼', '使', '无'],
brand_code: [{code: '1',isShow: true},{code: '2',isShow: true},{code: '3',isShow: true},{code: '4',isShow: true},{code: '5',isShow: true},{code: '6',isShow: true},{code: '7',isShow: true},{code: '8',isShow: true},{code: '9',isShow: true},{code: '0',isShow: true},{code: 'Q',isShow: true},{code: 'W',isShow: true},{code: 'E',isShow: true},{code: 'R',isShow: true},{code: 'T',isShow: true},{code: 'Y',isShow: true},{code: 'U',isShow: true},{code: 'O',isShow: false},{code: 'P',isShow: true},{code: '港',isShow: false},{code: 'A',isShow: true},{code: 'S',isShow: true},{code: 'D',isShow: true},{code: 'F',isShow: true},{code: 'G',isShow: true},{code: 'H',isShow: true},{code: 'J',isShow: true},{code: 'K',isShow: true},{code: 'L',isShow: true},{code: '澳',isShow: false},{code: 'Z',isShow: true},{code: 'X',isShow: true},{code: 'C',isShow: true},{code: 'V',isShow: true},{code: 'B',isShow: true},{code: 'N',isShow: true},{code: 'M',isShow: true},{code: '学',isShow: false},{code: '领',isShow: false}],
}
},
watch: {
value: {
deep: true,
immediate: true,
handler(newV, oldV) {
if (newV) {
// ...
for (let i = 0; i < newV.length; i++) {
this.brand[i] = newV[i]
this.$set(this.brand, i, newV[i])
}
}
},
},
},
点击输入框时,要选中当前输入框
// 点击输入框时,需要展示键盘,并且记录当前的点击
onBrandClick(e) {
this.isActive = e.currentTarget.dataset.index
this.show = true
},
显示键盘的时候,要根据用户输入来调整键盘的显示,以及禁用的按钮
computed: {
// 显示省份键盘
isShowProvinceSelect() {
return this.isActive === 0
},
// 数字字符键盘
isShowBrandSelect() {
// 当输入第二位开始
if(this.isActive <= 0) return false
// 第二位不能是数字
if(this.isActive === 1) {
// 正则校验数字
const reg = /^[0-9]*$/
this.brand_code.forEach(item => {
if(reg.test(item.code)) item.isShow = false
})
} else if(this.isActive === 6){
// 第6位的时候,只有字母 "O" 是不能点的
this.brand_code.forEach(item => {
if(item.code === 'O') {
item.isShow = false
} else {
item.isShow = true
}
})
} else {
// 其他情况,这5个都不能点
const arr = ['学', '澳', '领', '港', 'O']
this.brand_code.forEach(item => {
if(arr.includes(item.code)) {
item.isShow = false
} else {
item.isShow = true
}
})
}
return true
}
},
点击省份键盘和数字键盘
// 点击省份键盘
provinceClick(e) {
// 赋值,并且自动进入下一个输入框
this.brand[this.isActive++] = e.currentTarget.dataset.item
// 如果输入到最后一位,要 -1
this.isActive = this.isActive === this.brand.length ? this.isActive - 1 : this.isActive
},
// 点击数字字母键盘
brandCodeHandler(e) {
// 当前元素不可点击,直接return
if (!e.currentTarget.dataset.item.isShow) return
// 获取一下当前元素
const item = e.currentTarget.dataset.item
this.brand[this.isActive++] = item.code
this.isActive = this.isActive === this.brand.length ? this.isActive - 1 : this.isActive
},
关闭键盘及删除按钮的处理
// 点击外部元素的时候,关闭键盘,并且输入完毕
handleClick() {
// copy一份
const str = [...this.brand]
// 如果输入的不是新能源车牌,去掉最后一位
if (str[str.length - 1] === '+') str.pop()
// 回调
this.$emit('input', str.join(''))
// 关闭
this.show = false
},
// 删除
clearHandler() {
// 最后一位了, return
if ( this.isActive < 0 ) return
// 复原一下
this.brand[this.isActive--] = this.isActive === 6 ? '+' : ''
},
// 取消,初始化
cancelHandler() {
this.show = false
this.brand = ['', '', '', '', '', '', '', '+']
this.isActive = 0
this.$emit('input', '')
}
最后就是引用
// 页面上引入
import CarNum from '@/components/carNum/index.vue'
export default {
components: {
CarNum
},
}
// html v-model 双向绑定
<CarNum v-model='carNum'></CarNum>
该代码已上传至 HBuilder X插件市场
完整代码请看 码云
完。