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插件市场

完整代码请看 码云

完。

posted @ 2022-06-10 17:46  Z、yx  阅读(1468)  评论(0编辑  收藏  举报