VUE+CSS变量实现验证码输入框

334 阅读1分钟

VUE+CSS变量实现验证码输入框

还是不会插图而且有小bug,欢迎大佬提出宝贵意见,仍然是使用input框

1.html部分

<template>
    <div class="box">
        <!-- 循环生成input 绑定keyup事件传入事件源,以及第几个input框 获取焦点的输入框添加高亮 -->
        <input
            :style="{ borderBottomColor: currentIndex === el ? 'var(--border-active-color)' : 'var(--border-deactive-color)' }"
            class="inp" @focus="currentIndex = el" @keyup="keyUpEvent($event, el)" type="text" maxlength="1"
            v-for="el in inpAry" :key="el" />
    </div>
</template>

2.CSS部分,还是设置了CSS变量

<style scoped>
.box {
    /* 各种样式的css变量 */
    --custom-box-width: 200px;
    --custom-box-height: 50px;
    --custom-font-size: 18px;
    --custom-font-color: purple;
    --border-bottom-width: 1px;
    --border-code-style: none;
    --border-deactive-color: grey;
    --border-active-color: hotpink;
    --border-radius: 0;
    --border-default-width: 20px;
    width: calc(var(--border-default-width) * 10);
    height: var(--custom-box-height);
    display: flex;
    justify-content: space-evenly;
    align-items: center;
}

.inp {
    width: calc(var(--custom-box-width) * 0.1);
    height: calc(var(--custom-box-height) * 0.7);
    line-height: calc(var(--custom-box-height) * 0.7);
    border: var(--border-code-style);
    outline: none;
    text-align: center;
    border-bottom: 1px solid red;
    border-bottom-width: var(--border-bottom-width);
    border-bottom-color: var(--border-deactive-color);
    font-size: var(--custom-font-size);
    color: var(--custom-font-color);
    border-radius: var(--border-radius);
}
</style>

3.js部分

<script lang="ts" setup>
import { ref, onMounted, watch } from 'vue';
// 控制高亮
const currentIndex = ref<number>(-1)
// 存储输入的数值
const totalCode = ref<any[]>([])
// 存储输入框个数以及位置的数组
const inpAry = ref<Array<any>>([]);
// 回传验证码的事件
const emit = defineEmits<{ (e: 'onFinish', data: Array<any>): void }>()
// 定义默认输入验证码位数
const props = defineProps({
    count: {
        type: Number,
        default: 4
    }
})
// 挂载后生成数组用于渲染input框
onMounted(() => {
    for (let index = 0; index < props.count; index++) {
        inpAry.value.push(index)
    }
})
//keyup回调函数
const keyUpEvent = (e: KeyboardEvent, i: number) => {
    let code = Number(e.key)//转number
    if (code >= 0 && code <= 9) {
        // 存储对应位置的验证码
        totalCode.value[i] = code
        let next = (e as any).target.nextElementSibling
        // 如果有下一个元素,下一个兄弟元素获取焦点
        if (next) {
            next.focus()
        }
    } else {
        //否则设置为空字符串
        (e as any).target.value = ''
    }
    let { key } = e
    //如果是删除或者回退键存储该验证码的下标替换为空字符串
    if (key === 'Backspace' || key === 'Delete') {
        totalCode.value[i] = ''
        const prev = (e as any).target.previousElementSibling;
        if (prev) prev.focus();
    }
    console.log(totalCode.value);
}
//watch监听验证码数组长度,数组不包含空字符串且长度等于4回传验证码数组
watch(() => totalCode.value.length, (newval: number) => {
    if (!totalCode.value.includes('') && newval === 4) {
        emit('onFinish', totalCode.value)
    }
})

原谅我的any,确实定义不明白了,而且实现双向绑定有点困难,已输入的部分再次输入,无法修改现有值,但是回传的

数据值会发生变化,回传的数据是数组,可以按需配置,CSS变量的定义逻辑有点小混乱,被输入值的问题卡住了,欢迎

大佬斧正,图依旧是不会插,可以复制代码试一试