uni-车牌输入功能,类似与支付宝密码框

 遇到这么一个需求:

 车牌号输入,并且是每次输入后,每一位输入字符在占一个格子。

由于车牌号的构成对于密码而言比较复杂,否则可以模拟一个键盘,来控制和判断输入的内容,这样这个效果就比较简单。但是用于车牌输入的键盘内容比较多,所以这边用另外的方法。

首先创建一个input

<input :focus="bFocus" type="text" v-model="sCar" class="ipt-hide" @input="fInput" :maxlength="bIsUnit?7:8" @blur="fBlur" />

添加一些基础的事件,并且将其隐藏,隐藏样式比较特殊,可在文末全部代码处查看

然后创建方框等元素

<view class="car-item" v-for="nIndex in cCarNum" :class="{active:nIndex===sCar.length}" :key="nIndex">
            {{sCar.split('')[nIndex]?sCar.split('')[nIndex].toUpperCase():''}}
        </view>

当点击方框时,输入框聚焦,然后输入的字符处理后挨个排放入框内。

但是这个完成后有个bug,

当输入字符后,经过多次修改,尤其是在请求之后,隐藏的输入框被聚焦时,光标会跳到最前,导致内容无法修改,或者输入的字符永远在已存在字符的前面。这种情况通过清空字符时解决不了的。

所以解决方案是在请求后重载组件,重载方法是在input上添加key,请求后改变key来实现组件重载

<comp-car @fCb="fCarIpt" ref="compcar" :key="nComp"></comp-car>

nComp: Math.random()

但是重载的方法在小程序上经过测试失效了,更改key并不能让组件重载,但是小程序内测试时也未出现该bug,所以小程序内就直接清空字符处理后不再进行更多操作;

组件的全部代码如下:

app:

<template>
    <view class="car" @tap="fFocus">
        <input :focus="bFocus" type="text" v-model="sCar" class="ipt-hide" @input="fInput" :maxlength="bIsUnit?7:8" @blur="fBlur" />
        <view class="car-item" v-for="nIndex in cCarNum" :class="{active:nIndex===sCar.length}" :key="nIndex">
            {{sCar.split('')[nIndex]?sCar.split('')[nIndex].toUpperCase():''}}
        </view>
        <view class="car-item car-change" @tap.stop="fChange"><i class="iconfont">&#xe627</i><text>{{bIsUnit?'新能源':'普通'}}</text></view>
    </view>

</template>

<script>
    export default {
        data() {
            return {
                sCar: '苏',
                bIsUnit: true,
                bFocus: false,
                cursor: 1
            }
        },
        computed: {
            cCarNum() {
                return this.bIsUnit ? [0, 1, 2, 3, 4, 5, 6] : [0, 1, 2, 3, 4, 5, 6, 7]; //车牌位数
            }
        },
        onLoad(option) {

        },
        methods: {
            fClear() {
                this.sCar = '苏';
                this.bIsUnit = true;
                this.bFocus = false;
            },
            fChange() {
                this.sCar = '苏';
                this.bFocus = false;
                this.bIsUnit = !this.bIsUnit;
                this.$emit('fCb', {
                    sCar: this.sCar.toUpperCase(),
                    bIsUnit: this.bIsUnit
                })
            },
            fBlur() {
                this.bFocus = false;
            },
            fFocus() {
                this.bFocus = true;
            },
            fInput() {
                this.$emit('fCb', {
                    sCar: this.sCar.toUpperCase(),
                    bIsUnit: this.bIsUnit
                })
            }
        },
        mounted() {
            this.fClear()
        }
    }
</script>

<style scoped lang="less">
    .car {
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
        height: 44px;
        width: 100%;
        padding: 5px;
        box-sizing: border-box;
    }

    .car-item {
        height: 42px;
        width: 36px;
        margin: 0 2px;
        text-align: center;
        line-height: 42px;
        color: #3e3e3e;
        font-size: 18px;
        border: 1px solid #b2b2b2;
        border-radius: 3px;
    }

    .active {
        border-color: #19bbff;
    }

    .ipt-hide {
        position: absolute;
        z-index: -1;
        left: -100%;
        opacity: 0
    }

    .car-change {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        border-style: dotted;
        font-size: 10px;
        line-height: 2;
        color: #7f7f7f;

        .iconfont {
            font-size: 10px;
        }
    }
</style>

小程序内代码稍有改动,遍历渲染字符串时可以直接使用数字而不用数组

小程序代码:

<template>
    <view class="car" @tap="fFocus">
        <input :focus="bFocus" type="text" v-model="sCar" class="ipt-hide" @input="fInput" :maxlength="cCarNum" @blur="fBlur" />
        <view class="car-item" v-for="nIndex in cCarNum" :class="{active:nIndex===sCar.length-1}":key="nIndex">
            {{sCar.split('')[nIndex]?sCar.split('')[nIndex].toUpperCase():''}}
        </view>
        <view class="car-item car-change" @tap.stop="fChange"><i class="iconfont">&#xe627</i><text>{{bIsUnit?'新能源':'普通'}}</text></view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                sCar: '苏',
                bIsUnit: true,
                bFocus: false
            }
        },
        computed: {
            cCarNum() {
                return this.bIsUnit ? 7 : 8; //车牌位数
            }
        },
        onLoad(option) {

        },
        methods: {
            fClear() {
                this.sCar = '苏';
                this.bIsUnit = true;
                this.bFocus = false;
            },
            fChange() {
                this.sCar = '苏';
                this.bFocus = false;
                this.bIsUnit = !this.bIsUnit;
            },
            fBlur() {
                this.bFocus = false;
            },
            fFocus() {
                this.bFocus = true;
            },
            fInput() {
                this.$emit('fCb', {
                    sCar: this.sCar.toUpperCase(),
                    bIsUnit: this.bIsUnit
                })
            }
        },
        mounted() {
            this.fClear()
        }
    }
</script>

<style scoped lang="less">
    .car {
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
        height: 42px;
        width: 100%;
        padding: 5px;
        box-sizing: border-box;
    }

    .car-item {
        height: 42px;
        width: 36px;
        margin: 0 2px;
        text-align: center;
        line-height: 42px;
        color: #3e3e3e;
        font-size: 18px;
        border: 1px solid #b2b2b2;
        border-radius: 3px;
    }

    .active {
        border-color: #19bbff;
    }

    .ipt-hide {
        position: absolute;
        z-index: -1;
        left: -100%;
        opacity: 0
    }

    .car-change {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        border-style: dotted;
        font-size: 10px;
        line-height: 2;
        color: #7f7f7f;

        .iconfont {
            font-size: 10px;
        }
    }
</style>

 

posted @ 2020-11-23 16:22  butchersheep  阅读(1202)  评论(0编辑  收藏  举报